diff --git a/src/Symfony/Component/HttpFoundation/Session.php b/src/Symfony/Component/HttpFoundation/Session.php index 721a6c7240b99..f40237676e4ab 100644 --- a/src/Symfony/Component/HttpFoundation/Session.php +++ b/src/Symfony/Component/HttpFoundation/Session.php @@ -22,6 +22,10 @@ */ class Session implements \Serializable { + const FLASH_INFO = 'info'; + const FLASH_WARNING = 'warning'; + const FLASH_ERROR = 'error'; + protected $storage; protected $started; protected $attributes; @@ -37,8 +41,8 @@ class Session implements \Serializable public function __construct(SessionStorageInterface $storage) { $this->storage = $storage; - $this->flashes = array(); - $this->oldFlashes = array(); + $this->flashes = array(self::FLASH_INFO => array()); + $this->oldFlashes = array(self::FLASH_INFO => array()); $this->attributes = array(); $this->started = false; $this->closed = false; @@ -174,7 +178,7 @@ public function clear() } $this->attributes = array(); - $this->flashes = array(); + $this->flashes = array(self::FLASH_INFO => array()); } /** @@ -215,29 +219,63 @@ public function getId() return $this->storage->getId(); } + /** + * Gets the flash messages of a given type. + * + * @param string $type + * + * @throws \InvalidArgumentException If non-existing $type is requested. + * + * @return array + */ + public function getFlashes($type = self::FLASH_INFO) + { + if (!isset($this->flashes[$type])) { + throw new \InvalidArgumentException(sprintf('Flash message type %s does not exist', $type)); + } + + return $this->flashes[$type]; + } + /** * Gets the flash messages. * * @return array */ - public function getFlashes() + public function getAllFlashes() { return $this->flashes; } + /** + * Sets the flash messages of a specific type. + * + * @param array $values + * @param string $type + */ + public function setFlashes($values, $type = self::FLASH_INFO) + { + if (false === $this->started) { + $this->start(); + } + + $this->flashes[$type] = $values; + $this->oldFlashes = array(self::FLASH_INFO => array()); + } + /** * Sets the flash messages. * * @param array $values */ - public function setFlashes($values) + public function setAllFlashes($values) { if (false === $this->started) { $this->start(); } $this->flashes = $values; - $this->oldFlashes = array(); + $this->oldFlashes = array(self::FLASH_INFO => array()); } /** @@ -245,12 +283,18 @@ public function setFlashes($values) * * @param string $name * @param string|null $default + * + * @throws InvalidArgumentException If unknown type specified. * - * @return string + * @return mixed */ - public function getFlash($name, $default = null) + public function getFlash($name, $default = null, $type = self::FLASH_INFO) { - return array_key_exists($name, $this->flashes) ? $this->flashes[$name] : $default; + if (!isset($this->flashes[$type])) { + throw new \InvalidArgumentException(sprintf('Unknown flash message type %s', $type)); + } + + return array_key_exists($name, $this->flashes[$type]) ? $this->flashes[$type][$name] : $default; } /** @@ -258,31 +302,39 @@ public function getFlash($name, $default = null) * * @param string $name * @param string $value + * @param string $type */ - public function setFlash($name, $value) + public function setFlash($name, $value, $type = self::FLASH_INFO) { if (false === $this->started) { $this->start(); } - $this->flashes[$name] = $value; - unset($this->oldFlashes[$name]); + $this->flashes[$type][$name] = $value; + unset($this->oldFlashes[$type][$name]); } /** * Checks whether a flash message exists. * * @param string $name + * @param string $type + * + * @throws InvalidArgumentException If unknown type specified. * * @return Boolean */ - public function hasFlash($name) + public function hasFlash($name, $type = self::FLASH_INFO) { if (false === $this->started) { $this->start(); } + + if (!isset($this->flashes[$type])) { + throw new \InvalidArgumentException(sprintf('Unknown flash message type %s', $type)); + } - return array_key_exists($name, $this->flashes); + return array_key_exists($name, $this->flashes[$type]); } /** @@ -290,13 +342,15 @@ public function hasFlash($name) * * @param string $name */ - public function removeFlash($name) + public function removeFlash($name, $type = self::FLASH_INFO) { if (false === $this->started) { $this->start(); } - unset($this->flashes[$name]); + if (isset($this->flashes[$type])) { + unset($this->flashes[$type][$name]); + } } /** @@ -308,17 +362,33 @@ public function clearFlashes() $this->start(); } - $this->flashes = array(); - $this->oldFlashes = array(); + $this->flashes = array(self::FLASH_INFO => array()); + $this->oldFlashes = array(self::FLASH_INFO => array()); + } + + /** + * Adds a generic flash message to the session. + * + * @param string $value + * @param string $type + */ + public function addFlash($value, $type = self::FLASH_INFO) + { + $this->flashes[$type][] = $value; } + /** + * Save session. + */ public function save() { if (false === $this->started) { $this->start(); } - $this->flashes = array_diff_key($this->flashes, $this->oldFlashes); + foreach ($this->flashes as $type => $flashes) { + $this->flashes[$type] = array_diff_key($flashes, $this->oldFlashes[$type]); + } $this->storage->write('_symfony2', array( 'attributes' => $this->attributes, @@ -327,6 +397,8 @@ public function save() } /** + * Close the session without writing saving it. + * * This method should be called when you don't want the session to be saved * when the Session object is garbaged collected (useful for instance when * you want to simulate the interaction of several users/sessions in a single @@ -344,14 +416,30 @@ public function __destruct() } } + /** + * Serialize the session storage driver. + * + * @return string + */ public function serialize() { return serialize($this->storage); } + /** + * Unserialize the SessionStorage. + * + * @param type $serialized + * + * @throws \InvalidArgumentException If serialized string is not an instance of SessionStorageInterface + */ public function unserialize($serialized) { - $this->storage = unserialize($serialized); + $storage = unserialize($serialized); + if (!$storage instanceof SessionStorageInterface) { + throw new \InvalidArgumentException('Serialized string passed does not unserialze to an instance of Symfony\\Component\\HttpFoundation\\SessionStorageInterface'); + } + $this->storage = $storage; $this->attributes = array(); $this->started = false; } diff --git a/tests/Symfony/Tests/Component/HttpFoundation/SessionTest.php b/tests/Symfony/Tests/Component/HttpFoundation/SessionTest.php index d5f615a6b1370..9a03b5cd1edab 100644 --- a/tests/Symfony/Tests/Component/HttpFoundation/SessionTest.php +++ b/tests/Symfony/Tests/Component/HttpFoundation/SessionTest.php @@ -22,7 +22,14 @@ */ class SessionTest extends \PHPUnit_Framework_TestCase { + /** + * @var SessionStorage + */ protected $storage; + + /** + * @var Session + */ protected $session; public function setUp() @@ -59,6 +66,55 @@ public function testFlash() $this->session->setFlashes($flashes); $this->assertSame($flashes, $this->session->getFlashes()); + + $this->session->clearFlashes(); + $this->session->addFlash('foo'); + $compare = $this->session->getFlashes(); + $this->assertSame($compare, array(0 => 'foo')); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testGetFlashException() + { + $this->session->getFlash('foo', null, 'notexisting'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testHasFlashException() + { + $this->session->hasFlash('foo', 'notexisting'); + } + + public function testGetFlashes() + { + $this->assertEquals(array(), $this->session->getFlashes(Session::FLASH_INFO)); + $this->session->setFlash(Session::FLASH_INFO, 'hello'); + $this->assertEquals(array(Session::FLASH_INFO => 'hello'), $this->session->getFlashes(Session::FLASH_INFO)); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testGetFlashesException() + { + $this->session->getFlashes('notexisting'); + } + + public function testSetFlashes() + { + $this->session->setFlashes(array('hello', 'world')); + $this->assertEquals(array('hello', 'world'), $this->session->getFlashes(Session::FLASH_INFO)); + } + + public function testAllFlashes() + { + $this->assertEquals(array(Session::FLASH_INFO => array()), $this->session->getAllFlashes()); + $this->session->setAllFlashes(array(Session::FLASH_INFO => array('hello', 'world'))); + $this->assertEquals(array(Session::FLASH_INFO => array('hello', 'world')), $this->session->getAllFlashes()); } public function testFlashesAreFlushedWhenNeeded() @@ -141,6 +197,15 @@ public function testSerialize() $this->assertEquals($_storage->getValue($this->session), $this->storage, 'storage match'); } + + /** + * @expectedException InvalidArgumentException + */ + public function testUnserializeException() + { + $serialized = serialize('not an instance of SessionStorage'); + $this->session->unserialize($serialized); + } public function testSave() { @@ -149,7 +214,7 @@ public function testSave() $this->session->set('foo', 'bar'); $this->session->save(); - $compare = array('_symfony2' => array('attributes' => array('foo' => 'bar'), 'flashes' => array())); + $compare = array('_symfony2' => array('attributes' => array('foo' => 'bar'), 'flashes' => array(Session::FLASH_INFO => array()))); $r = new \ReflectionObject($this->storage); $p = $r->getProperty('data'); @@ -179,7 +244,7 @@ public function testSavedOnDestruct() $expected = array( 'attributes'=>array('foo'=>'bar'), - 'flashes'=>array(), + 'flashes'=>array(Session::FLASH_INFO => array()), ); $saved = $this->storage->read('_symfony2'); $this->assertSame($expected, $saved); @@ -195,7 +260,7 @@ public function testSavedOnDestructAfterManualSave() $expected = array( 'attributes'=>array('foo'=>'bar'), - 'flashes'=>array(), + 'flashes'=>array(Session::FLASH_INFO => array()), ); $saved = $this->storage->read('_symfony2'); $this->assertSame($expected, $saved);