diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 597b65b3f6..cf1b16435b 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -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 ----- diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index a1fcf539f8..e55cb39500 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -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]; diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php index 280630914a..9fa851d4b5 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php @@ -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); } /** diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 4b9be5e9b2..c3c8e38494 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -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]; diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php index 711eaa29a3..cfd785c663 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php @@ -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. * diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php index 2a6f6bb7e8..55d0fc01d1 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php @@ -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()); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php index d42c62a25c..4c9fcfa52e 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 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()); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index b99941aa2c..17a25076fe 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -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()); + } }