[HttpFoundation] Changed meta-data responsibility to

SessionStorageInterface

Added cookie_lifetime to the meta-data.  This allows to know how old
a cookie is and when the cookie will expire.
This commit is contained in:
Drak 2012-03-29 17:15:37 +05:45
parent d9fd14f261
commit 402254ca7e
7 changed files with 126 additions and 35 deletions

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\HttpFoundation\Session; namespace Symfony\Component\HttpFoundation\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MetaBag;
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
@ -46,20 +47,14 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
*/ */
private $attributeName; private $attributeName;
/**
* @var string
*/
private $metaName;
/** /**
* Constructor. * 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 AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag)
* @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag) * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag)
* @param MetaBag $meta A MetaBag instance (defaults null for default MetaBag)
*/ */
public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, MetaBag $meta = null) public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null)
{ {
$this->storage = $storage ?: new NativeSessionStorage(); $this->storage = $storage ?: new NativeSessionStorage();
@ -70,10 +65,6 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
$flashes = $flashes ?: new FlashBag(); $flashes = $flashes ?: new FlashBag();
$this->flashName = $flashes->getName(); $this->flashName = $flashes->getName();
$this->registerBag($flashes); $this->registerBag($flashes);
$metaBag = $meta ?: new MetaBag();
$this->metaName = $metaBag->getName();
$this->registerBag($metaBag);
} }
/** /**
@ -225,7 +216,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
*/ */
public function getMeta() public function getMeta()
{ {
return $this->getBag($this->metaName); return $this->storage->getMetaBag();
} }
/** /**

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Symfony\Component\HttpFoundation\Session; namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
@ -47,12 +47,12 @@ class MetaBag implements SessionBagInterface
/** /**
* Constructor. * Constructor.
* *
* @param string $storageKey The key used to store flashes in the session. * @param string $storageKey The key used to store bag in the session.
*/ */
public function __construct($storageKey = '_sf2_meta') public function __construct($storageKey = '_sf2_meta')
{ {
$this->storageKey = $storageKey; $this->storageKey = $storageKey;
$this->meta = array('created' => 0, 'lastused' => 0); $this->meta = array('created' => 0, 'lastused' => 0, 'lifetime' => 0);
} }
/** /**
@ -66,21 +66,23 @@ class MetaBag implements SessionBagInterface
$this->lastUsed = $this->meta['lastused']; $this->lastUsed = $this->meta['lastused'];
$this->meta['lastused'] = time(); $this->meta['lastused'] = time();
} else { } else {
$this->meta['created'] = $this->meta['lastused'] = $this->lastUsed = time(); $this->stampCreated();
} }
} }
/** /**
* {@inheritdoc} * Gets the lifetime that this cooke was set with.
*
* @return integer
*/ */
public function getName() public function getLifetime()
{ {
return $this->name; return $this->meta['lifetime'];
} }
public function setName($name) public function stampNew()
{ {
$this->name = $name; $this->stampCreated();
} }
/** /**
@ -118,4 +120,24 @@ class MetaBag implements SessionBagInterface
{ {
// nothing to do // nothing to do
} }
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
private function stampCreated()
{
$timeStamp = time();//(null === $timeStamp) ? time() : $timeStamp;
$this->meta['created'] = $this->meta['lastused'] = $this->lastUsed = $timeStamp;
$this->meta['lifetime'] = ini_get('session.cookie_lifetime');
}
} }

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation\Session\Storage; namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\MetaBag;
/** /**
* MockArraySessionStorage mocks the session for unit tests. * MockArraySessionStorage mocks the session for unit tests.
@ -52,14 +53,21 @@ class MockArraySessionStorage implements SessionStorageInterface
*/ */
protected $data = array(); protected $data = array();
/**
* @var MetaBag
*/
protected $metaBag;
/** /**
* Constructor. * Constructor.
* *
* @param string $name Session name * @param string $name Session name
* @param MetaBag $metaBag MetaBag instance.
*/ */
public function __construct($name = 'MOCKSESSID') public function __construct($name = 'MOCKSESSID', MetaBag $metaBag = null)
{ {
$this->name = $name; $this->name = $name;
$this->setMetaBag($metaBag);
} }
/** /**
@ -100,6 +108,10 @@ class MockArraySessionStorage implements SessionStorageInterface
$this->start(); $this->start();
} }
if ($destroy) {
$this->metaBag->stampNew();
}
$this->id = $this->generateId(); $this->id = $this->generateId();
return true; return true;
@ -191,6 +203,30 @@ class MockArraySessionStorage implements SessionStorageInterface
return $this->bags[$name]; return $this->bags[$name];
} }
/**
* Sets the metabag.
*
* @param MetaBag $metaBag
*/
public function setMetaBag(MetaBag $metaBag = null)
{
if (null === $metaBag) {
$metaBag = new MetaBag();
}
$this->metaBag = $metaBag;
}
/**
* Gets the MetaBag.
*
* @return MetaBag
*/
public function getMetaBag()
{
return $this->metaBag;
}
/** /**
* Generates a session ID. * Generates a session ID.
* *
@ -206,7 +242,9 @@ class MockArraySessionStorage implements SessionStorageInterface
protected function loadSession() protected function loadSession()
{ {
foreach ($this->bags as $bag) { $bags = array_merge($this->bags, array($this->metaBag));
foreach ($bags as $bag) {
$key = $bag->getStorageKey(); $key = $bag->getStorageKey();
$this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array(); $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array();
$bag->initialize($this->data[$key]); $bag->initialize($this->data[$key]);

View File

@ -75,8 +75,13 @@ class MockFileSessionStorage extends MockArraySessionStorage
*/ */
public function regenerate($destroy = false) public function regenerate($destroy = false)
{ {
if (!$this->started) {
$this->start();
}
if ($destroy) { if ($destroy) {
$this->destroy(); $this->destroy();
$this->metaBag->stampNew();
} }
$this->id = $this->generateId(); $this->id = $this->generateId();

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation\Session\Storage; namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\MetaBag;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
@ -45,6 +46,11 @@ class NativeSessionStorage implements SessionStorageInterface
*/ */
protected $saveHandler; protected $saveHandler;
/**
* @var MetaBag
*/
protected $metaBag;
/** /**
* Constructor. * Constructor.
* *
@ -83,10 +89,11 @@ class NativeSessionStorage implements SessionStorageInterface
* upload_progress.min-freq, "1" * upload_progress.min-freq, "1"
* url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
* *
* @param array $options Session configuration options. * @param array $options Session configuration options.
* @param object $handler SessionHandlerInterface. * @param object $handler SessionHandlerInterface.
* @param MetaBag $handler MetaBag.
*/ */
public function __construct(array $options = array(), $handler = null) public function __construct(array $options = array(), $handler = null, MetaBag $metaBag = null)
{ {
// sensible defaults // sensible defaults
ini_set('session.auto_start', 0); // by default we prefer to explicitly start the session using the class. ini_set('session.auto_start', 0); // by default we prefer to explicitly start the session using the class.
@ -99,6 +106,7 @@ class NativeSessionStorage implements SessionStorageInterface
register_shutdown_function('session_write_close'); register_shutdown_function('session_write_close');
} }
$this->setMetaBag($metaBag);
$this->setOptions($options); $this->setOptions($options);
$this->setSaveHandler($handler); $this->setSaveHandler($handler);
} }
@ -189,6 +197,10 @@ class NativeSessionStorage implements SessionStorageInterface
*/ */
public function regenerate($destroy = false) public function regenerate($destroy = false)
{ {
if ($destroy) {
$this->metaBag->stampNew();
}
return session_regenerate_id($destroy); return session_regenerate_id($destroy);
} }
@ -249,6 +261,30 @@ class NativeSessionStorage implements SessionStorageInterface
return $this->bags[$name]; return $this->bags[$name];
} }
/**
* Sets the metabag.
*
* @param MetaBag $metaBag
*/
public function setMetaBag(MetaBag $metaBag = null)
{
if (null === $metaBag) {
$metaBag = new MetaBag();
}
$this->metaBag = $metaBag;
}
/**
* Gets the MetaBag.
*
* @return MetaBag
*/
public function getMetaBag()
{
return $this->metaBag;
}
/** /**
* Sets session.* ini variables. * Sets session.* ini variables.
* *
@ -338,7 +374,9 @@ class NativeSessionStorage implements SessionStorageInterface
$session = &$_SESSION; $session = &$_SESSION;
} }
foreach ($this->bags as $bag) { $bags = array_merge($this->bags, array($this->metaBag));
foreach ($bags as $bag) {
$key = $bag->getStorageKey(); $key = $bag->getStorageKey();
$session[$key] = isset($session[$key]) ? $session[$key] : array(); $session[$key] = isset($session[$key]) ? $session[$key] : array();
$bag->initialize($session[$key]); $bag->initialize($session[$key]);

View File

@ -257,9 +257,6 @@ class SessionTest extends \PHPUnit_Framework_TestCase
public function testGetMeta() public function testGetMeta()
{ {
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\MetaBag', $this->session->getMeta()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\MetaBag', $this->session->getMeta());
$metaBag = new MetaBag();
$session = new Session($this->storage, new AttributeBag(), new FlashBag(), $metaBag);
$this->assertSame($metaBag, $session->getBag($metaBag->getName()));
} }
} }

View File

@ -9,9 +9,9 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Symfony\Component\HttpFoundation\Tests\Session; namespace Symfony\Component\HttpFoundation\Tests\Session\Storage;
use Symfony\Component\HttpFoundation\Session\MetaBag; use Symfony\Component\HttpFoundation\Session\Storage\MetaBag;
/** /**
* Test class for MetaBag. * Test class for MetaBag.
@ -43,7 +43,7 @@ class MetaBagTest extends \PHPUnit_Framework_TestCase
public function testInitialize() public function testInitialize()
{ {
$p = new \ReflectionProperty('Symfony\Component\HttpFoundation\Session\MetaBag', 'meta'); $p = new \ReflectionProperty('Symfony\Component\HttpFoundation\Session\Storage\MetaBag', 'meta');
$p->setAccessible(true); $p->setAccessible(true);
$bag1 = new MetaBag(); $bag1 = new MetaBag();