diff --git a/src/Symfony/Component/HttpFoundation/AutoExpireFlashBag.php b/src/Symfony/Component/HttpFoundation/AutoExpireFlashBag.php new file mode 100644 index 0000000000..5c435a2821 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/AutoExpireFlashBag.php @@ -0,0 +1,168 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * AutoExpireFlashBag flash message container. + * + * @author Drak + */ +class AutoExpireFlashBag implements FlashBagInterface +{ + /** + * Flash messages. + * + * @var array + */ + private $flashes = array(); + + /** + * The storage key for flashes in the session + * + * @var string + */ + private $storageKey; + + /** + * Constructor. + * + * @param type $storageKey The key used to store flashes in the session. + */ + public function __construct($storageKey = '_sf2_flashes') + { + $this->storageKey = $storageKey; + $this->flashes = array('display' => array(), 'new' => array()); + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$flashes) + { + $this->flashes = &$flashes; + + // The logic: messages from the last request will be stored in new, so we move them to previous + // This request we will show what is in 'display'. What is placed into 'new' this time round will + // be moved to display next time round. + $this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : array(); + $this->flashes['new'] = array(); + } + + /** + * {@inheritdoc} + */ + public function add($message, $type = self::NOTICE) + { + $this->flashes['new'][$type][] = $message; + } + + /** + * {@inheritdoc} + */ + public function get($type) + { + if (!$this->has($type)) { + return array(); + } + + return $this->flashes['display'][$type]; + } + + /** + * {@inheritdoc} + */ + public function pop($type) + { + if (!$this->has($type)) { + return array(); + } + + return $this->clear($type); + } + + /** + * {@inheritdoc} + */ + public function popAll() + { + return $this->clearAll(); + } + + /** + * {@inheritdoc} + */ + public function set($type, array $array) + { + $this->flashes['new'][$type] = $array; + } + + /** + * {@inheritdoc} + */ + public function has($type) + { + return array_key_exists($type, $this->flashes['display']); + } + + /** + * {@inheritdoc} + */ + public function keys() + { + return array_keys($this->flashes['display']); + } + + /** + * {@inheritdoc} + */ + public function all() + { + return array_key_exists('display', $this->flashes) ? (array)$this->flashes['display'] : array(); + } + + /** + * {@inheritdoc} + */ + public function clear($type) + { + $return = array(); + if (isset($this->flashes['new'][$type])) { + unset($this->flashes['new'][$type]); + } + + if (isset($this->flashes['display'][$type])) { + $return = $this->flashes['display'][$type]; + unset($this->flashes['display'][$type]); + } + + return $return; + } + + /** + * {@inheritdoc} + */ + public function clearAll() + { + $return = $this->flashes['display']; + $this->flashes = array('new' => array(), 'display' => array()); + + return $return; + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } +} diff --git a/src/Symfony/Component/HttpFoundation/FlashBag.php b/src/Symfony/Component/HttpFoundation/FlashBag.php new file mode 100644 index 0000000000..89d7dfffc2 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/FlashBag.php @@ -0,0 +1,157 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * FlashBag flash message container. + * + * @author Drak + */ +class FlashBag implements FlashBagInterface +{ + /** + * Flash messages. + * + * @var array + */ + private $flashes = array(); + + /** + * The storage key for flashes in the session + * + * @var string + */ + private $storageKey; + + /** + * Constructor. + * + * @param type $storageKey The key used to store flashes in the session. + */ + public function __construct($storageKey = '_sf2_flashes') + { + $this->storageKey = $storageKey; + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$flashes) + { + $this->flashes = &$flashes; + } + + /** + * {@inheritdoc} + */ + public function add($message, $type = self::NOTICE) + { + $this->flashes[$type][] = $message; + } + + /** + * {@inheritdoc} + */ + public function get($type) + { + if (!$this->has($type)) { + return array(); + } + + return $this->flashes[$type]; + } + + /** + * {@inheritdoc} + */ + public function pop($type) + { + if (!$this->has($type)) { + return array(); + } + + return $this->clear($type); + } + + /** + * {@inheritdoc} + */ + public function popAll() + { + return $this->clearAll(); + } + + /** + * {@inheritdoc} + */ + public function set($type, array $array) + { + $this->flashes[$type] = $array; + } + + /** + * {@inheritdoc} + */ + public function has($type) + { + return array_key_exists($type, $this->flashes); + } + + /** + * {@inheritdoc} + */ + public function keys() + { + return array_keys($this->flashes); + } + + /** + * {@inheritdoc} + */ + public function all() + { + return $this->flashes; + } + + /** + * {@inheritdoc} + */ + public function clear($type) + { + $return = array(); + if (isset($this->flashes[$type])) { + $return = $this->flashes[$type]; + unset($this->flashes[$type]); + } + + return $return; + } + + /** + * {@inheritdoc} + */ + public function clearAll() + { + $return = $this->flashes; + $this->flashes = array(); + + return $return; + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } +} diff --git a/src/Symfony/Component/HttpFoundation/FlashBagInterface.php b/src/Symfony/Component/HttpFoundation/FlashBagInterface.php new file mode 100644 index 0000000000..89ea8e197b --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/FlashBagInterface.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; + +/** + * FlashBagInterface. + * + * @author Drak + */ +interface FlashBagInterface +{ + const INFO = 'info'; + const NOTICE = 'notice'; + const WARNING = 'warning'; + const ERROR = 'error'; + + /** + * Initializes the FlashBag. + * + * @param array &$flashes + */ + function initialize(array &$flashes); + + /** + * Adds a flash to the stack for a given type. + * + * @param string $message + * @param string $type + */ + function add($message, $type = self::NOTICE); + + /** + * Gets flash messages for a given type. + * + * @param string $type Message category type. + * + * @return array + */ + function get($type); + + /** + * Pops and clears flashes from the stack. + * + * @param string $type + * + * @return array + */ + function pop($type); + + /** + * Pops all flashes from the stacl and clears flashes. + * + * @param string $type + * + * @return array Empty array, or indexed array of arrays. + */ + function popAll(); + + /** + * Sets an array of flash messages for a given type. + * + * @param string $type + * @param array $array + */ + function set($type, array $array); + + /** + * Has flash messages for a given type? + * + * @param string $type + * + * @return boolean + */ + function has($type); + + /** + * Returns a list of all defined types. + * + * @return array + */ + function keys(); + + /** + * Gets all flash messages. + * + * @return array + */ + function all(); + + /** + * Clears flash messages for a given type. + * + * @param string $type + * + * @return array Returns an array of what was just cleared. + */ + function clear($type); + + /** + * Clears all flash messages. + * + * @return array Empty array or indexed arrays or array if none. + */ + function clearAll(); + + /** + * Gets the storage key for this bag. + * + * @return string + */ + function getStorageKey(); +} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/AutoExpireFlashBagTest.php b/tests/Symfony/Tests/Component/HttpFoundation/AutoExpireFlashBagTest.php new file mode 100644 index 0000000000..d3c21c6c06 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/AutoExpireFlashBagTest.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpFoundation; + +use Symfony\Component\HttpFoundation\AutoExpireFlashBag as FlashBag; +use Symfony\Component\HttpFoundation\FlashBagInterface; + +/** + * AutoExpireFlashBagTest + * + * @author Drak + */ +class AutoExpireFlashBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\HttpFoundation\FlashBagInterface + */ + private $bag; + + /** + * @var array + */ + protected $array = array(); + + public function setUp() + { + parent::setUp(); + $this->bag = new FlashBag(); + $this->array = array('new' => array(FlashBag::NOTICE => array('A previous flash message'))); + $this->bag->initialize($this->array); + } + + public function tearDown() + { + $this->bag = null; + parent::tearDown(); + } + + public function testInitialize() + { + $bag = new FlashBag(); + $array = array('new' => array(FlashBag::NOTICE => array('A previous flash message'))); + $bag->initialize($array); + $this->assertEquals(array('A previous flash message'), $bag->get(FlashBag::NOTICE)); + $array = array('new' => array( + FlashBag::NOTICE => array('Something else'), + FlashBag::ERROR => array('a', 'b'), + )); + $bag->initialize($array); + $this->assertEquals(array('Something else'), $bag->get(FlashBag::NOTICE)); + $this->assertEquals(array('a', 'b'), $bag->get(FlashBag::ERROR)); + } + + public function testAdd() + { + $this->bag->add('Something new', FlashBag::NOTICE); + $this->bag->add('Smile, it might work next time', FlashBag::ERROR); + $this->assertEquals(array('A previous flash message'), $this->bag->get(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->get(FlashBag::ERROR)); + } + + public function testGet() + { + $this->assertEquals(array('A previous flash message'), $this->bag->get(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->get('non_existing_type')); + } + + public function testSet() + { + $this->bag->set(FlashBag::NOTICE, array('Foo', 'Bar')); + $this->assertNotEquals(array('Foo', 'Bar'), $this->bag->get(FlashBag::NOTICE)); + } + + public function testHas() + { + $this->assertFalse($this->bag->has('nothing')); + $this->assertTrue($this->bag->has(FlashBag::NOTICE)); + } + + public function testKeys() + { + $this->assertEquals(array(FlashBag::NOTICE), $this->bag->keys()); + } + + public function testAll() + { + $array = array( + 'new' => array( + FlashBag::NOTICE => array('Foo'), + FlashBag::ERROR => array('Bar'), + ), + ); + + $this->bag->initialize($array); + $this->assertEquals(array( + FlashBag::NOTICE => array('Foo'), + FlashBag::ERROR => array('Bar'), + ), $this->bag->all() + ); + } + + public function testPop() + { + $this->assertEquals(array('A previous flash message'), $this->bag->pop(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->pop(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->pop('non_existing_type')); + } + + public function testPopAll() + { + $this->bag->set(FlashBag::NOTICE, array('Foo')); + $this->bag->set(FlashBag::ERROR, array('Bar')); + $this->assertEquals(array( + FlashBag::NOTICE => array('A previous flash message'), + ), $this->bag->popAll() + ); + + $this->assertEquals(array(), $this->bag->popAll()); + } + + public function testClear() + { + $this->assertTrue($this->bag->has(FlashBag::NOTICE)); + $this->assertEquals(array('A previous flash message'), $this->bag->clear(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->clear(FlashBag::NOTICE)); + $this->assertFalse($this->bag->has(FlashBag::NOTICE)); + } + + public function testClearAll() + { + $this->assertTrue($this->bag->has(FlashBag::NOTICE)); + $this->bag->add('Smile, it might work next time', FlashBag::ERROR); + $this->assertFalse($this->bag->has(FlashBag::ERROR)); + $this->assertEquals(array( + FlashBag::NOTICE => array('A previous flash message'), + ), $this->bag->clearAll() + ); + $this->assertEquals(array(), $this->bag->clearAll()); + $this->assertFalse($this->bag->has(FlashBag::NOTICE)); + $this->assertFalse($this->bag->has(FlashBag::ERROR)); + } + +} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/FlashBagTest.php b/tests/Symfony/Tests/Component/HttpFoundation/FlashBagTest.php new file mode 100644 index 0000000000..0d5a8a1ac5 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/FlashBagTest.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Tests\Component\HttpFoundation; + +use Symfony\Component\HttpFoundation\FlashBag; +use Symfony\Component\HttpFoundation\FlashBagInterface; + +/** + * FlashBagTest + * + * @author Drak + */ +class FlashBagTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\HttpFoundation\FlashBagInterface + */ + private $bag; + + /** + * @var array + */ + protected $array = array(); + + public function setUp() + { + parent::setUp(); + $this->bag = new FlashBag(); + $this->array = array(FlashBag::NOTICE => array('A previous flash message')); + $this->bag->initialize($this->array); + } + + public function tearDown() + { + $this->bag = null; + parent::tearDown(); + } + + public function testInitialize() + { + $bag = new FlashBag(); + $bag->initialize($this->array); + $this->assertEquals($this->array, $bag->all()); + $array = array('should' => array('change')); + $bag->initialize($array); + $this->assertEquals($array, $bag->all()); + } + + public function testAdd() + { + $this->bag->add('Something new', FlashBag::NOTICE); + $this->bag->add('Smile, it might work next time', FlashBag::ERROR); + $this->assertEquals(array('A previous flash message', 'Something new'), $this->bag->get(FlashBag::NOTICE)); + $this->assertEquals(array('Smile, it might work next time'), $this->bag->get(FlashBag::ERROR)); + } + + public function testGet() + { + $this->assertEquals(array('A previous flash message'), $this->bag->get(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->get('non_existing_type')); + } + + public function testPop() + { + $this->assertEquals(array('A previous flash message'), $this->bag->pop(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->pop(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->pop('non_existing_type')); + } + + public function testPopAll() + { + $this->bag->set(FlashBag::NOTICE, array('Foo')); + $this->bag->set(FlashBag::ERROR, array('Bar')); + $this->assertEquals(array( + FlashBag::NOTICE => array('Foo'), + FlashBag::ERROR => array('Bar')), $this->bag->popAll() + ); + + $this->assertEquals(array(), $this->bag->popAll()); + } + + public function testSet() + { + $this->bag->set(FlashBag::NOTICE, array('Foo', 'Bar')); + $this->assertEquals(array('Foo', 'Bar'), $this->bag->get(FlashBag::NOTICE)); + } + + public function testHas() + { + $this->assertFalse($this->bag->has('nothing')); + $this->assertTrue($this->bag->has(FlashBag::NOTICE)); + } + + public function testKeys() + { + $this->assertEquals(array(FlashBag::NOTICE), $this->bag->keys()); + } + + public function testAll() + { + $this->bag->set(FlashBag::NOTICE, array('Foo')); + $this->bag->set(FlashBag::ERROR, array('Bar')); + $this->assertEquals(array( + FlashBag::NOTICE => array('Foo'), + FlashBag::ERROR => array('Bar')), $this->bag->all() + ); + $this->assertTrue($this->bag->has(FlashBag::NOTICE)); + $this->assertTrue($this->bag->has(FlashBag::ERROR)); + $this->assertEquals(array( + FlashBag::NOTICE => array('Foo'), + FlashBag::ERROR => array('Bar'), + ), $this->bag->all() + ); + } + + public function testClear() + { + $this->assertTrue($this->bag->has(FlashBag::NOTICE)); + $this->assertEquals(array('A previous flash message'), $this->bag->clear(FlashBag::NOTICE)); + $this->assertEquals(array(), $this->bag->clear(FlashBag::NOTICE)); + $this->assertFalse($this->bag->has(FlashBag::NOTICE)); + } + + public function testClearAll() + { + $this->assertTrue($this->bag->has(FlashBag::NOTICE)); + $this->bag->add('Smile, it might work next time', FlashBag::ERROR); + $this->assertTrue($this->bag->has(FlashBag::ERROR)); + $this->assertEquals(array( + FlashBag::NOTICE => array('A previous flash message'), + FlashBag::ERROR => array('Smile, it might work next time'), + ), $this->bag->clearAll() + ); + $this->assertEquals(array(), $this->bag->clearAll()); + $this->assertFalse($this->bag->has(FlashBag::NOTICE)); + $this->assertFalse($this->bag->has(FlashBag::ERROR)); + } + +}