Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[2.3][Session] Give greater control over how and when session starts #7855

Open
wants to merge 3 commits into from

0 participants

@ghost
Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets na
License MIT
Doc PR symfony/symfony-docs#2475

Gives control over how start on demand works: allowing to turn it on or off and to allow bag access when session is off.

Rationale:
ON/OFF - Currently a session is auto-started on demand. This may not be desirable and it does make debugging code very difficult if you need to determine when and where magic is happening. This simply gives control.

OFF_LAX - this could be removed from the PR but it emulates native PHP behaviour when you can still read/write $_SESSION before a session is started.

Drak Revert "Revert "merged branch drak/start_on_demand (PR #7576)""
This reverts commit 5a3428dc7818195bf907639e26a4cf45340830b8.
eaf3f75
@ghost Show outdated diff Hide outdated diff Unknown commented on an outdated diff
...tpFoundation/Session/Storage/NativeSessionStorage.php
@@ -53,14 +53,25 @@ class NativeSessionStorage implements SessionStorageInterface
protected $metadataBag;
/**
+ * @var Boolean
+ */
+ protected $mode;
+
+ /**
+ * @var Boolean
+ */
+ protected $emulatePhp;
@ghost
ghost added a note

Unused property

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 20, 2013
  1. Revert "Revert "merged branch drak/start_on_demand (PR #7576)""

    Drak authored
    This reverts commit 5a3428dc7818195bf907639e26a4cf45340830b8.
Commits on Apr 26, 2013
  1. Remove unused property.

    Drak authored
  2. Update PhpBridgeSessionStorage

    Drak authored
This page is out of date. Refresh to see the latest.
Showing with 233 additions and 71 deletions.
  1. +2 −0  src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
  2. +10 −0 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
  3. +9 −0 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
  4. +8 −2 src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php
  5. +3 −0  src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
  6. +8 −0 src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml
  7. +2 −0  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
  8. +1 −1  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
  9. +2 −0  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
  10. +3 −0  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
  11. +1 −0  src/Symfony/Component/HttpFoundation/CHANGELOG.md
  12. +1 −1  src/Symfony/Component/HttpFoundation/Session/Session.php
  13. +1 −1  src/Symfony/Component/HttpFoundation/Session/SessionBagInterface.php
  14. +8 −8 src/Symfony/Component/HttpFoundation/Session/SessionInterface.php
  15. +1 −1  src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php
  16. +1 −1  src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php
  17. +2 −2 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php
  18. +3 −3 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php
  19. +7 −7 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php
  20. +2 −2 src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php
  21. +13 −4 src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php
  22. +7 −11 src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php
  23. +17 −9 src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
  24. +3 −1 src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php
  25. +5 −5 src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php
  26. +1 −1  src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php
  27. +24 −8 src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php
  28. +29 −1 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php
  29. +30 −2 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockFileSessionStorageTest.php
  30. +29 −0 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php
View
2  src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -13,6 +13,8 @@ CHANGELOG
* added support for default templates per render tag
* added FormHelper::form(), FormHelper::start() and FormHelper::end()
* deprecated FormHelper::enctype() in favor of FormHelper::start()
+ * Reintroduce `auto_start` session config flag to instruct the `SessionListener` to manually start session
+ * Added session config option `on_demand_mode` to control session start on demand.
2.2.0
-----
View
10 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -198,6 +198,16 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
->info('session configuration')
->canBeUnset()
->children()
+ ->booleanNode('auto_start')
+ ->defaultFalse()
+ ->info('Flag for SessionListener to start session')
+ ->end()
+ ->enumNode('on_demand_mode')
+ ->values(array('off', 'on', 'off_lax'))
+ ->defaultValue('on')
+ ->info('Start session on demand: off, on, or off_lax')
+ ->end()
+ ->scalarNode('mock_name')->defaultValue('MOCKSESSID')->end()
->scalarNode('storage_id')->defaultValue('session.storage.native')->end()
->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end()
->scalarNode('name')->end()
View
9 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -18,6 +18,7 @@
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Finder\Finder;
+use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Config\FileLocator;
@@ -314,6 +315,14 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c
$container->setParameter('session.storage.options', $options);
+ // this controls the SessionListener to start session
+ $container->setParameter('session.auto_start', $config['auto_start']);
+
+ // this controls the session start on demand feature
+ $container->setParameter('session.storage.on_demand_mode', $config['on_demand_mode']);
+
+ $container->setParameter('session.storage.mock_name', $config['mock_name']);
+
// session handler (the internal callback registered with PHP session management)
if (null == $config['handler_id']) {
// Set the handler class to be null
View
10 src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php
@@ -29,10 +29,12 @@ class SessionListener implements EventSubscriberInterface
* @var ContainerInterface
*/
private $container;
+ private $autoStart;
- public function __construct(ContainerInterface $container)
+ public function __construct(ContainerInterface $container, $autoStart = false)
{
$this->container = $container;
+ $this->autoStart = $autoStart;
}
public function onKernelRequest(GetResponseEvent $event)
@@ -46,7 +48,11 @@ public function onKernelRequest(GetResponseEvent $event)
return;
}
- $request->setSession($this->container->get('session'));
+ $request->setSession($session = $this->container->get('session'));
+
+ if ($this->autoStart || $request->hasPreviousSession()) {
+ $session->start();
+ }
}
public static function getSubscribedEvents()
View
3  src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -77,6 +77,9 @@
</xsd:complexType>
<xsd:complexType name="session">
+ <xsd:attribute name="auto-start" type="xsd:boolean" />
+ <xsd:attribute name="on-demand-mode" type="xsd:string" />
+ <xsd:attribute name="mock-name" type="xsd:string" />
<xsd:attribute name="storage-id" type="xsd:string" />
<xsd:attribute name="handler-id" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
View
8 src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml
@@ -8,6 +8,7 @@
<parameter key="session.class">Symfony\Component\HttpFoundation\Session\Session</parameter>
<parameter key="session.flashbag.class">Symfony\Component\HttpFoundation\Session\Flash\FlashBag</parameter>
<parameter key="session.attribute_bag.class">Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag</parameter>
+ <parameter key="session.metadata_bag.class">Symfony\Component\HttpFoundation\Session\Storage\MetadataBag</parameter>
<parameter key="session.storage.native.class">Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage</parameter>
<parameter key="session.storage.php_bridge.class">Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage</parameter>
<parameter key="session.storage.mock_file.class">Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage</parameter>
@@ -25,6 +26,8 @@
<service id="session.storage.native" class="%session.storage.native.class%">
<argument>%session.storage.options%</argument>
<argument type="service" id="session.handler" />
+ <argument type="service" id="session.metadata_bag" />
+ <argument>%session.storage.on_demand_mode%</argument>
</service>
<service id="session.storage.php_bridge" class="%session.storage.php_bridge.class%">
@@ -32,11 +35,15 @@
</service>
<service id="session.flash_bag" class="%session.flashbag.class%" public="false" />
+ <service id="session.metadata_bag" class="%session.metadata_bag.class%" public="false" />
<service id="session.attribute_bag" class="%session.attribute_bag.class%" public="false" />
<service id="session.storage.mock_file" class="%session.storage.mock_file.class%" public="false">
<argument>%kernel.cache_dir%/sessions</argument>
+ <argument>%session.storage.mock_name%</argument>
+ <argument type="service" id="session.metadata_bag" />
+ <argument>%session.storage.on_demand_mode%</argument>
</service>
<service id="session.handler.native_file" class="%session.handler.native_file.class%" public="false">
@@ -46,6 +53,7 @@
<service id="session_listener" class="%session_listener.class%">
<tag name="kernel.event_subscriber" />
<argument type="service" id="service_container" />
+ <argument>%session.auto_start%</argument>
</service>
<!-- for BC -->
View
2  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
@@ -24,6 +24,8 @@
'session' => array(
'storage_id' => 'session.storage.native',
'handler_id' => 'session.handler.native_file',
+ 'auto_start' => true,
+ 'on_demand_mode' => 'on',
'name' => '_SYMFONY',
'cookie_lifetime' => 86400,
'cookie_path' => '/',
View
2  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
@@ -12,7 +12,7 @@
<framework:esi enabled="true" />
<framework:profiler only-exceptions="true" enabled="false" />
<framework:router resource="%kernel.root_dir%/config/routing.xml" type="xml" />
- <framework:session gc-maxlifetime="90000" gc-probability="1" gc-divisor="108" storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" cookie-lifetime="86400" cookie-path="/" cookie-domain="example.com" cookie-secure="true" cookie-httponly="true" save-path="/path/to/sessions" />
+ <framework:session gc-maxlifetime="90000" gc-probability="1" gc-divisor="108" storage-id="session.storage.native" handler-id="session.handler.native_file" name="_SYMFONY" cookie-lifetime="86400" cookie-path="/" cookie-domain="example.com" cookie-secure="true" cookie-httponly="true" save-path="/path/to/sessions" auto-start="true" on-demand-mode="on" />
<framework:templating assets-version="SomeVersionScheme" cache="/path/to/cache" >
<framework:loader>loader.foo</framework:loader>
<framework:loader>loader.bar</framework:loader>
View
2  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
@@ -18,6 +18,8 @@ framework:
session:
storage_id: session.storage.native
handler_id: session.handler.native_file
+ auto_start: true
+ on_demand_mode: on
name: _SYMFONY
cookie_lifetime: 86400
cookie_path: /
View
3  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -97,6 +97,9 @@ public function testSession()
$this->assertEquals('session.storage.native', (string) $container->getAlias('session.storage'));
$this->assertEquals('session.handler.native_file', (string) $container->getAlias('session.handler'));
+ $this->assertTrue($container->getParameter('session.auto_start'));
+ $this->assertEquals($container->getParameter('session.storage.on_demand_mode'), 'on');
+
$options = $container->getParameter('session.storage.options');
$this->assertEquals('_SYMFONY', $options['name']);
$this->assertEquals(86400, $options['cookie_lifetime']);
View
1  src/Symfony/Component/HttpFoundation/CHANGELOG.md
@@ -6,6 +6,7 @@ CHANGELOG
* added support for ranges of IPs in trusted proxies
* `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode)
+ * added control for session start on demand.
2.2.0
-----
View
2  src/Symfony/Component/HttpFoundation/Session/Session.php
@@ -49,7 +49,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* Constructor.
*
- * @param SessionStorageInterface $storage A SessionStorageInterface instance.
+ * @param SessionStorageInterface $storage A SessionStorageInterface instance
* @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag)
* @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag)
*/
View
2  src/Symfony/Component/HttpFoundation/Session/SessionBagInterface.php
@@ -42,7 +42,7 @@ public function getStorageKey();
/**
* Clears out data from bag.
*
- * @return mixed Whatever data was contained.
+ * @return mixed Whatever data was contained
*/
public function clear();
}
View
16 src/Symfony/Component/HttpFoundation/Session/SessionInterface.php
@@ -23,9 +23,9 @@
/**
* Starts the session storage.
*
- * @return Boolean True if session started.
+ * @return Boolean True if session started
*
- * @throws \RuntimeException If session fails to start.
+ * @throws \RuntimeException If session fails to start
*
* @api
*/
@@ -34,7 +34,7 @@ public function start();
/**
* Returns the session ID.
*
- * @return string The session ID.
+ * @return string The session ID
*
* @api
*/
@@ -52,7 +52,7 @@ public function setId($id);
/**
* Returns the session name.
*
- * @return mixed The session name.
+ * @return mixed The session name
*
* @api
*/
@@ -76,9 +76,9 @@ public function setName($name);
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
- * not a Unix timestamp.
+ * not a Unix timestamp
*
- * @return Boolean True if session invalidated, false if error.
+ * @return Boolean True if session invalidated, false if error
*
* @api
*/
@@ -92,9 +92,9 @@ public function invalidate($lifetime = null);
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
- * not a Unix timestamp.
+ * not a Unix timestamp
*
- * @return Boolean True if session migrated, false if error.
+ * @return Boolean True if session migrated, false if error
*
* @api
*/
View
2  src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php
@@ -29,7 +29,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface
private $ttl;
/**
- * @var string Key prefix for shared environments.
+ * @var string Key prefix for shared environments
*/
private $prefix;
View
2  src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php
@@ -34,7 +34,7 @@ class MemcachedSessionHandler implements \SessionHandlerInterface
private $ttl;
/**
- * @var string Key prefix for shared environments.
+ * @var string Key prefix for shared environments
*/
private $prefix;
View
4 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php
@@ -52,11 +52,11 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
public function __construct($mongo, array $options)
{
if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) {
- throw new \InvalidArgumentException('MongoClient or Mongo instance required');
+ throw new \InvalidArgumentException('MongoClient or Mongo instance required.');
}
if (!isset($options['database']) || !isset($options['collection'])) {
- throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler');
+ throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.');
}
$this->mongo = $mongo;
View
6 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php
@@ -24,10 +24,10 @@ class NativeFileSessionHandler extends NativeSessionHandler
* Constructor.
*
* @param string $savePath Path of directory to save session files.
- * Default null will leave setting as defined by PHP.
+ * Default null will leave setting as defined by PHP
* '/path', 'N;/path', or 'N;octal-mode;/path
*
- * @see http://php.net/session.configuration.php#ini.session.save-path for further details.
+ * @see http://php.net/session.configuration.php#ini.session.save-path for further details
*
* @throws \InvalidArgumentException On invalid $savePath
*/
@@ -41,7 +41,7 @@ public function __construct($savePath = null)
if ($count = substr_count($savePath, ';')) {
if ($count > 2) {
- throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath));
+ throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'.', $savePath));
}
// characters after last ';' are the path
View
14 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php
@@ -20,12 +20,12 @@
class PdoSessionHandler implements \SessionHandlerInterface
{
/**
- * @var \PDO PDO instance.
+ * @var \PDO PDO instance
*/
private $pdo;
/**
- * @var array Database options.
+ * @var array Database options
*/
private $dbOptions;
@@ -90,7 +90,7 @@ public function destroy($id)
$stmt->bindParam(':id', $id, \PDO::PARAM_STR);
$stmt->execute();
} catch (\PDOException $e) {
- throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
+ throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s.', $e->getMessage()), 0, $e);
}
return true;
@@ -113,7 +113,7 @@ public function gc($lifetime)
$stmt->bindValue(':time', time() - $lifetime, \PDO::PARAM_INT);
$stmt->execute();
} catch (\PDOException $e) {
- throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e);
+ throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s.', $e->getMessage()), 0, $e);
}
return true;
@@ -149,7 +149,7 @@ public function read($id)
return '';
} catch (\PDOException $e) {
- throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e);
+ throw new \RuntimeException(sprintf('PDOException was thrown when trying to read the session data: %s.', $e->getMessage()), 0, $e);
}
}
@@ -204,7 +204,7 @@ public function write($id, $data)
}
}
} catch (\PDOException $e) {
- throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e);
+ throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s.', $e->getMessage()), 0, $e);
}
return true;
@@ -216,7 +216,7 @@ public function write($id, $data)
* @param string $id
* @param string $data
*
- * @return boolean True.
+ * @return boolean True
*/
private function createNewSession($id, $data = '')
{
View
4 src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php
@@ -51,7 +51,7 @@ class MetadataBag implements SessionBagInterface
/**
* Constructor.
*
- * @param string $storageKey The key used to store bag in the session.
+ * @param string $storageKey The key used to store bag in the session
*/
public function __construct($storageKey = '_sf2_meta')
{
@@ -90,7 +90,7 @@ public function getLifetime()
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
- * not a Unix timestamp.
+ * not a Unix timestamp
*/
public function stampNew($lifetime = null)
{
View
17 src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php
@@ -64,15 +64,22 @@ class MockArraySessionStorage implements SessionStorageInterface
protected $bags;
/**
+ * @var Boolean
+ */
+ protected $mode;
+
+ /**
* Constructor.
*
* @param string $name Session name
- * @param MetadataBag $metaBag MetadataBag instance.
+ * @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;
}
/**
@@ -160,7 +167,7 @@ public function setName($name)
public function save()
{
if (!$this->started || $this->closed) {
- throw new \RuntimeException("Trying to save a session that was not started yet or was already closed");
+ throw new \RuntimeException("Trying to save a session that was not started yet or was already closed.");
}
// nothing to do since we don't persist the session data
$this->closed = false;
@@ -200,8 +207,10 @@ public function getBag($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 not been started.');
}
return $this->bags[$name];
View
18 src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php
@@ -30,18 +30,14 @@ 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 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 @@ public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag
$this->savePath = $savePath;
- parent::__construct($name, $metaBag);
+ parent::__construct($name, $metaBag, $mode);
}
/**
@@ -98,7 +94,7 @@ public function regenerate($destroy = false, $lifetime = null)
public function save()
{
if (!$this->started) {
- throw new \RuntimeException("Trying to save a session that was not started yet or was already closed");
+ throw new \RuntimeException("Trying to save a session that was not started yet or was already closed.");
}
file_put_contents($this->getFilePath(), serialize($this->data));
View
26 src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
@@ -53,14 +53,20 @@ class NativeSessionStorage implements SessionStorageInterface
protected $metadataBag;
/**
+ * @var Boolean
+ */
+ protected $mode;
+
+ /**
* Constructor.
*
* Depending on how you want the storage driver to behave you probably
* 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).
@@ -92,11 +98,12 @@ class NativeSessionStorage implements SessionStorageInterface
* upload_progress.min-freq, "1"
* url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
*
- * @param array $options Session configuration options.
+ * @param array $options Session configuration options
* @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
- * @param MetadataBag $metaBag MetadataBag.
+ * @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);
@@ -110,6 +117,7 @@ public function __construct(array $options = array(), $handler = null, MetadataB
$this->setMetadataBag($metaBag);
$this->setOptions($options);
$this->setSaveHandler($handler);
+ $this->mode = $mode;
}
/**
@@ -146,7 +154,7 @@ public function start()
// ok to try and start the session
if (!session_start()) {
- throw new \RuntimeException('Failed to start the session');
+ throw new \RuntimeException('Failed to start the session.');
}
$this->loadSession();
@@ -259,10 +267,10 @@ public function getBag($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 not been started.');
}
return $this->bags[$name];
@@ -306,7 +314,7 @@ public function isStarted()
* For convenience we omit 'session.' from the beginning of the keys.
* Explicitly ignores other ini keys.
*
- * @param array $options Session ini directives array(key => value).
+ * @param array $options Session ini directives array(key => value)
*
* @see http://php.net/session.configuration
*/
View
4 src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php
@@ -27,11 +27,13 @@ class PhpBridgeSessionStorage extends NativeSessionStorage
*
* @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
* @param MetadataBag $metaBag MetadataBag
+ * @param string $mode
*/
- public function __construct($handler = null, MetadataBag $metaBag = null)
+ public function __construct($handler = null, MetadataBag $metaBag = null, $mode = self::START_ON_DEMAND)
{
$this->setMetadataBag($metaBag);
$this->setSaveHandler($handler);
+ $this->mode = $mode;
}
/**
View
10 src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php
@@ -36,7 +36,7 @@
protected $saveHandlerName;
/**
- * Gets the session.save_handler name.
+ * Gets the session.save_handler name
*
* @return string
*/
@@ -46,7 +46,7 @@ public function getSaveHandlerName()
}
/**
- * Is this proxy handler and instance of \SessionHandlerInterface.
+ * Is this proxy handler and instance of \SessionHandlerInterface
*
* @return boolean
*/
@@ -56,7 +56,7 @@ public function isSessionHandlerInterface()
}
/**
- * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
+ * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler
*
* @return Boolean
*/
@@ -120,7 +120,7 @@ public function getId()
public function setId($id)
{
if ($this->isActive()) {
- throw new \LogicException('Cannot change the ID of an active session');
+ throw new \LogicException('Cannot change the ID of an active session.');
}
session_id($id);
@@ -146,7 +146,7 @@ public function getName()
public function setName($name)
{
if ($this->isActive()) {
- throw new \LogicException('Cannot change the name of an active session');
+ throw new \LogicException('Cannot change the name of an active session.');
}
session_name($name);
View
2  src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php
@@ -32,7 +32,7 @@ public function __construct()
/**
* Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
*
- * @return Boolean False.
+ * @return Boolean False
*/
public function isWrapper()
{
View
32 src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php
@@ -25,11 +25,27 @@
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 = 'off';
+
+ /**
+ * Start the session on demand when accessing bag data.
+ */
+ const START_ON_DEMAND = 'on';
+
+ /**
+ * Do not start session on demand but allow access to session bags.
+ */
+ const NO_START_ON_DEMAND_LAX = 'off_lax';
+
+ /**
* Starts the session.
*
- * @throws \RuntimeException If something goes wrong starting the session.
+ * @throws \RuntimeException If something goes wrong starting the session
*
- * @return boolean True if started.
+ * @return boolean True if started
*
* @api
*/
@@ -38,14 +54,14 @@ public function start();
/**
* Checks if the session is started.
*
- * @return boolean True if started, false otherwise.
+ * @return boolean True if started, false otherwise
*/
public function isStarted();
/**
* Returns the session ID
*
- * @return string The session ID or empty.
+ * @return string The session ID or empty
*
* @api
*/
@@ -63,7 +79,7 @@ public function setId($id);
/**
* Returns the session name
*
- * @return mixed The session name.
+ * @return mixed The session name
*
* @api
*/
@@ -89,11 +105,11 @@ public function setName($name);
* Note regenerate+destroy should not clear the session data in memory
* only delete the session data from persistent storage.
*
- * @param Boolean $destroy Destroy session when regenerating?
+ * @param Boolean $destroy Flag true to destroy session when regenerating
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
- * not a Unix timestamp.
+ * not a Unix timestamp
*
* @return Boolean True if session regenerated, false if error
*
@@ -112,7 +128,7 @@ public function regenerate($destroy = false, $lifetime = null);
* it should actually persist the session data if required.
*
* @throws \RuntimeException If the session is saved without being started, or if the session
- * is already closed.
+ * is already closed
*/
public function save();
View
30 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php
@@ -97,10 +97,38 @@ public function testGetId()
}
/**
- * @expectedException RuntimeException
+ * @expectedException \RuntimeException
*/
public function testUnstartedSave()
{
$this->storage->save();
}
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testStartOnDemandException()
+ {
+ $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
32 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 @@ public function testMultipleInstances()
}
/**
- * @expectedException RuntimeException
+ * @expectedException \RuntimeException
*/
public function testSaveWithoutStart()
{
@@ -123,4 +123,32 @@ private function getStorage()
return $storage;
}
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testStartOnDemandException()
+ {
+ $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
29 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php
@@ -20,6 +20,7 @@
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
+use Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler\NativeSessionHandlerTest;
/**
* Test class for NativeSessionStorage.
@@ -279,4 +280,32 @@ public function destroy($id)
public function gc($maxlifetime)
{
}
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testStartOnDemandException()
+ {
+ $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());
+ }
}
Something went wrong with that request. Please try again.