From 29bd787b7e4828ac9f28c5714a46ff455f587113 Mon Sep 17 00:00:00 2001 From: Drak Date: Wed, 28 Mar 2012 21:07:12 +0545 Subject: [PATCH] [HttpFoundation] Added some basic meta-data to Session This commit allows applications to know certain meta-data about the session Session storage is designed to only store some data against a session ID so this method is necessary to be compatible with any session handler, including native handlers. --- .../HttpFoundation/Session/MetaBag.php | 121 ++++++++++++++++++ .../HttpFoundation/Session/Session.php | 74 +++++++---- .../Session/SessionInterface.php | 23 ++++ .../Tests/Session/SessionTest.php | 9 ++ .../HttpFoundation/Session/MetaBagTest.php | 100 +++++++++++++++ 5 files changed, 300 insertions(+), 27 deletions(-) create mode 100644 src/Symfony/Component/HttpFoundation/Session/MetaBag.php create mode 100644 tests/Symfony/Tests/Component/HttpFoundation/Session/MetaBagTest.php diff --git a/src/Symfony/Component/HttpFoundation/Session/MetaBag.php b/src/Symfony/Component/HttpFoundation/Session/MetaBag.php new file mode 100644 index 0000000000..53b9bf6a33 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/MetaBag.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + +/** + * Metadata container. + * + * Adds standard meta data to the session. + * + * @author Drak + */ +class MetaBag implements SessionBagInterface +{ + /** + * @var string + */ + private $name = '__meta'; + + /** + * @var string + */ + private $storageKey; + + /** + * @var array + */ + protected $meta = array(); + + /** + * Unix timestamp. + * + * @var integer + */ + private $lastUsed; + + /** + * Constructor. + * + * @param string $storageKey The key used to store flashes in the session. + */ + public function __construct($storageKey = '_sf2_meta') + { + $this->storageKey = $storageKey; + $this->meta = array('created' => 0, 'lastused' => 0); + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$meta) + { + $this->meta = &$meta; + + if (isset($meta['created'])) { + $this->lastUsed = $this->meta['lastused']; + $this->meta['lastused'] = time(); + } else { + $this->meta['created'] = $this->meta['lastused'] = $this->lastUsed = time(); + } + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + public function setName($name) + { + $this->name = $name; + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } + + /** + * Gets the created timestamp meta data. + * + * @return integer Unix timestamp + */ + public function getCreated() + { + return $this->meta['created']; + } + + /** + * Gets the last used meta data. + * + * @return integer Unix timestamp + */ + public function getLastUsed() + { + return $this->lastUsed; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + // nothing to do + } +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Session.php b/src/Symfony/Component/HttpFoundation/Session/Session.php index 145f96440f..d67cc55220 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Session.php +++ b/src/Symfony/Component/HttpFoundation/Session/Session.php @@ -46,24 +46,34 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable */ private $attributeName; + /** + * @var string + */ + private $metaName; + /** * Constructor. * * @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) + * @param MetaBag $meta A MetaBag instance (defaults null for default MetaBag) */ - public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) + public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, MetaBag $meta = null) { $this->storage = $storage ?: new NativeSessionStorage(); - $attributeBag = $attributes ?: new AttributeBag(); - $this->attributeName = $attributeBag->getName(); - $this->registerBag($attributeBag); + $attributes = $attributes ?: new AttributeBag(); + $this->attributeName = $attributes->getName(); + $this->registerBag($attributes); - $flashBag = $flashes ?: new FlashBag(); - $this->flashName = $flashBag->getName(); - $this->registerBag($flashBag); + $flashes = $flashes ?: new FlashBag(); + $this->flashName = $flashes->getName(); + $this->registerBag($flashes); + + $metaBag = $meta ?: new MetaBag(); + $this->metaName = $metaBag->getName(); + $this->registerBag($metaBag); } /** @@ -130,6 +140,26 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable $this->storage->getBag($this->attributeName)->clear(); } + /** + * Returns an iterator for attributes. + * + * @return \ArrayIterator An \ArrayIterator instance + */ + public function getIterator() + { + return new \ArrayIterator($this->storage->getBag($this->attributeName)->all()); + } + + /** + * Returns the number of attributes. + * + * @return int The number of attributes + */ + public function count() + { + return count($this->storage->getBag($this->attributeName)->all()); + } + /** * {@inheritdoc} */ @@ -188,6 +218,16 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable $this->storage->setName($name); } + /** + * Gets session meta. + * + * @return MetaBag + */ + public function getMeta() + { + return $this->getBag($this->metaName); + } + /** * Registers a SessionBagInterface with the session. * @@ -310,24 +350,4 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable { return $this->getBag($this->flashName)->clear(); } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator An \ArrayIterator instance - */ - public function getIterator() - { - return new \ArrayIterator($this->storage->getBag('attributes')->all()); - } - - /** - * Returns the number of attributes. - * - * @return int The number of attributes - */ - public function count() - { - return count($this->storage->getBag('attributes')->all()); - } } diff --git a/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php b/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php index 4e4962de4e..7cd6f95ea4 100644 --- a/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php +++ b/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php @@ -164,4 +164,27 @@ interface SessionInterface * @api */ function clear(); + + /** + * Gets session meta. + * + * @return MetaBag + */ + public function getMeta(); + + /** + * Registers a SessionBagInterface with the session. + * + * @param SessionBagInterface $bag + */ + public function registerBag(SessionBagInterface $bag); + + /** + * Get's a bag instance. + * + * @param string $name + * + * @return SessionBagInterface + */ + public function getBag($name); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php index 79a4068a5d..9505a7450d 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Tests\Session; use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\MetaBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; @@ -253,4 +254,12 @@ class SessionTest extends \PHPUnit_Framework_TestCase $this->assertEquals(2, count($this->session)); } + + public function testGetMeta() + { + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\MetaBag', $this->session->getMeta()); + $metaBag = new MetaBag(); + $session = new Session($this->storage, new AttributeBag(), new FlashBag(), $metaBag); + $this->assertSame($metaBag, $session->getBag($metaBag->getName())); + } } diff --git a/tests/Symfony/Tests/Component/HttpFoundation/Session/MetaBagTest.php b/tests/Symfony/Tests/Component/HttpFoundation/Session/MetaBagTest.php new file mode 100644 index 0000000000..e6ca9911a9 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/Session/MetaBagTest.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpFoundation\Session; + +use Symfony\Component\HttpFoundation\Session\MetaBag; + +/** + * Test class for MetaBag. + */ +class MetaBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var MetaBag + */ + protected $bag; + + /** + * @var array + */ + protected $array = array(); + + protected function setUp() + { + $this->bag = new MetaBag(); + $this->array = array('created' => 1234567, 'lastused' => 12345678); + $this->bag->initialize($this->array); + } + + protected function tearDown() + { + $this->array = array(); + $this->bag = null; + } + + public function testInitialize() + { + $p = new \ReflectionProperty('Symfony\Component\HttpFoundation\Session\MetaBag', 'meta'); + $p->setAccessible(true); + + $bag1 = new MetaBag(); + $array = array(); + $bag1->initialize($array); + $this->assertGreaterThanOrEqual(time(), $bag1->getCreated()); + $this->assertEquals($bag1->getCreated(), $bag1->getLastUsed()); + + sleep(1); + $bag2 = new MetaBag(); + $array2 = $p->getValue($bag1); + $bag2->initialize($array2); + $this->assertEquals($bag1->getCreated(), $bag2->getCreated()); + $this->assertEquals($bag1->getLastUsed(), $bag2->getLastUsed()); + $this->assertEquals($bag2->getCreated(), $bag2->getLastUsed()); + + sleep(1); + $bag3 = new MetaBag(); + $array3 = $p->getValue($bag2); + $bag3->initialize($array3); + $this->assertEquals($bag1->getCreated(), $bag3->getCreated()); + $this->assertGreaterThan($bag2->getLastUsed(), $bag3->getLastUsed()); + $this->assertNotEquals($bag3->getCreated(), $bag3->getLastUsed()); + } + + public function testGetSetName() + { + $this->assertEquals('__meta', $this->bag->getName()); + $this->bag->setName('foo'); + $this->assertEquals('foo', $this->bag->getName()); + + } + + public function testGetStorageKey() + { + $this->assertEquals('_sf2_meta', $this->bag->getStorageKey()); + } + + public function testGetCreated() + { + $this->assertEquals(1234567, $this->bag->getCreated()); + } + + public function testGetLastUsed() + { + $this->assertLessThanOrEqual(time(), $this->bag->getLastUsed()); + } + + public function testClear() + { + $this->bag->clear(); + } + +}