[HttpFoundation] Give control over how session start on demand.

This allows control over how the session start on demand works

0: no start on demand when bags are accessed
1: start session if bags are accessed
2: no start on demand when bags are accessed but still return bag contents
This commit is contained in:
Drak 2013-04-06 10:32:48 +01:00
parent a7c9863b3a
commit 8fc2397760
8 changed files with 140 additions and 20 deletions

View File

@ -4,6 +4,7 @@ CHANGELOG
2.3.0
* `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode)
* addded control for session start on demand.
2.2.0
-----

View File

@ -63,16 +63,23 @@ class MockArraySessionStorage implements SessionStorageInterface
*/
protected $bags;
/**
* @var Boolean
*/
protected $mode;
/**
* Constructor.
*
* @param string $name Session name
* @param string $name Session name.
* @param MetadataBag $metaBag MetadataBag instance.
* @param integer $mode Session on demand mode.
*/
public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null)
public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null, $mode = self::START_ON_DEMAND)
{
$this->name = $name;
$this->setMetadataBag($metaBag);
$this->mode = $mode;
}
/**
@ -197,11 +204,13 @@ class MockArraySessionStorage implements SessionStorageInterface
public function getBag($name)
{
if (!isset($this->bags[$name])) {
throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered', $name));
}
if (!$this->started) {
if (!$this->started && self::START_ON_DEMAND === $this->mode) {
$this->start();
} elseif (!$this->started && self::NO_START_ON_DEMAND_STRICT === $this->mode) {
throw new \RuntimeException('Cannot access session bags because the session has been started');
}
return $this->bags[$name];

View File

@ -29,19 +29,15 @@ class MockFileSessionStorage extends MockArraySessionStorage
*/
private $savePath;
/**
* @var array
*/
private $sessionData;
/**
* Constructor.
*
* @param string $savePath Path of directory to save session files.
* @param string $name Session name.
* @param MetadataBag $metaBag MetadataBag instance.
* @param integer $mode Start on demand mode.
*/
public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null)
public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null, $mode = self::START_ON_DEMAND)
{
if (null === $savePath) {
$savePath = sys_get_temp_dir();
@ -53,7 +49,7 @@ class MockFileSessionStorage extends MockArraySessionStorage
$this->savePath = $savePath;
parent::__construct($name, $metaBag);
parent::__construct($name, $metaBag, $mode);
}
/**

View File

@ -51,6 +51,16 @@ class NativeSessionStorage implements SessionStorageInterface
*/
protected $metadataBag;
/**
* @var Boolean
*/
protected $mode;
/**
* @var Boolean
*/
protected $emulatePhp;
/**
* Constructor.
*
@ -58,8 +68,9 @@ class NativeSessionStorage implements SessionStorageInterface
* want to override this constructor entirely.
*
* List of options for $options array with their defaults.
*
* @see http://php.net/session.configuration for options
* but we omit 'session.' from the beginning of the keys for convenience.
* but we omit 'session.' from the beginning of the keys for convenience.
*
* ("auto_start", is not supported as it tells PHP to start a session before
* PHP starts to execute user-land code. Setting during runtime has no effect).
@ -94,8 +105,9 @@ class NativeSessionStorage implements SessionStorageInterface
* @param array $options Session configuration options.
* @param object $handler SessionHandlerInterface.
* @param MetadataBag $metaBag MetadataBag.
* @param integer $mode Start on demand mode.
*/
public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null, $mode = self::START_ON_DEMAND)
{
ini_set('session.cache_limiter', ''); // disable by default because it's managed by HeaderBag (if used)
ini_set('session.use_cookies', 1);
@ -109,6 +121,7 @@ class NativeSessionStorage implements SessionStorageInterface
$this->setMetadataBag($metaBag);
$this->setOptions($options);
$this->setSaveHandler($handler);
$this->mode = $mode;
}
/**
@ -253,13 +266,13 @@ class NativeSessionStorage implements SessionStorageInterface
public function getBag($name)
{
if (!isset($this->bags[$name])) {
throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered', $name));
}
if ($this->saveHandler->isActive() && !$this->started) {
$this->loadSession();
} elseif (!$this->started) {
if (!$this->started && self::START_ON_DEMAND === $this->mode) {
$this->start();
} elseif (!$this->started && self::NO_START_ON_DEMAND_STRICT === $this->mode) {
throw new \RuntimeException('Cannot access session bags because the session has been started');
}
return $this->bags[$name];

View File

@ -24,6 +24,22 @@ use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
*/
interface SessionStorageInterface
{
/**
* Do not start session on demand and throw exception if attempt
* is make to read or write bag data.
*/
const NO_START_ON_DEMAND_STRICT = 0;
/**
* Start the session on demand when accessing bag data.
*/
const START_ON_DEMAND = 1;
/**
* Do not start session on demand but allow access to session bags.
*/
const NO_START_ON_DEMAND_LAX = 2;
/**
* Starts the session.
*

View File

@ -97,10 +97,38 @@ class MockArraySessionStorageTest extends \PHPUnit_Framework_TestCase
}
/**
* @expectedException RuntimeException
* @expectedException \RuntimeException
*/
public function testUnstartedSave()
{
$this->storage->save();
}
/**
* @expectedException \RuntimeException
*/
public function testtStartOnDemandException()
{
$storage = new MockArraySessionStorage('MOCKSESSID', null, MockArraySessionStorage::NO_START_ON_DEMAND_STRICT);
$storage->registerBag(new AttributeBag);
$this->assertFalse($storage->isStarted());
$storage->getBag('attributes');
}
public function testStartOnDemandDefaults()
{
$storage = new MockArraySessionStorage('MOCKSESSID');
$storage->registerBag(new AttributeBag);
$storage->getBag('attributes');
$this->assertTrue($storage->isStarted());
}
public function testNoStartOnDemandLax()
{
$storage = new MockArraySessionStorage('MOCKSESSID', null, MockArraySessionStorage::NO_START_ON_DEMAND_LAX);
$storage->registerBag($bag = new AttributeBag);
$bag->set('foo', 'bar');
$storage->getBag('attributes');
$this->assertEquals(array('foo' => 'bar'), $storage->getBag('attributes')->all());
}
}

View File

@ -28,7 +28,7 @@ class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase
private $sessionDir;
/**
* @var FileMockSessionStorage
* @var MockFileSessionStorage
*/
protected $storage;
@ -107,7 +107,7 @@ class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase
}
/**
* @expectedException RuntimeException
* @expectedException \RuntimeException
*/
public function testSaveWithoutStart()
{
@ -123,4 +123,32 @@ class MockFileSessionStorageTest extends \PHPUnit_Framework_TestCase
return $storage;
}
/**
* @expectedException \RuntimeException
*/
public function testtStartOnDemandException()
{
$storage = new MockFileSessionStorage($this->sessionDir, 'MOCKSESSID', null, MockFileSessionStorage::NO_START_ON_DEMAND_STRICT);
$storage->registerBag(new AttributeBag);
$this->assertFalse($storage->isStarted());
$storage->getBag('attributes');
}
public function testStartOnDemandDefaults()
{
$storage = new MockFileSessionStorage($this->sessionDir, 'MOCKSESSID');
$storage->registerBag(new AttributeBag);
$storage->getBag('attributes');
$this->assertTrue($storage->isStarted());
}
public function testNoStartOnDemandLax()
{
$storage = new MockFileSessionStorage($this->sessionDir, 'MOCKSESSID', null, MockFileSessionStorage::NO_START_ON_DEMAND_LAX);
$storage->registerBag($bag = new AttributeBag);
$bag->set('foo', 'bar');
$storage->getBag('attributes');
$this->assertEquals(array('foo' => 'bar'), $storage->getBag('attributes')->all());
}
}

View File

@ -16,6 +16,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHa
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler\NativeSessionHandlerTest;
/**
* Test class for NativeSessionStorage.
@ -154,4 +155,32 @@ class NativeSessionStorageTest extends \PHPUnit_Framework_TestCase
$storage->setSaveHandler(new NullSessionHandler());
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler());
}
/**
* @expectedException \RuntimeException
*/
public function testtStartOnDemandException()
{
$storage = new NativeSessionStorage(array(), null, null, NativeSessionStorage::NO_START_ON_DEMAND_STRICT);
$storage->registerBag(new AttributeBag);
$this->assertFalse($storage->isStarted());
$storage->getBag('attributes');
}
public function testStartOnDemandDefaults()
{
$storage = new NativeSessionStorage();
$storage->registerBag(new AttributeBag);
$storage->getBag('attributes');
$this->assertTrue($storage->isStarted());
}
public function testNoStartOnDemandLax()
{
$storage = new NativeSessionStorage(array(), null, null, NativeSessionStorage::NO_START_ON_DEMAND_LAX);
$storage->registerBag($bag = new AttributeBag);
$bag->set('foo', 'bar');
$storage->getBag('attributes');
$this->assertEquals(array('foo' => 'bar'), $storage->getBag('attributes')->all());
}
}