Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\HttpFoundation\Session\Storage; Chris@0: Chris@0: use Symfony\Component\HttpFoundation\Session\SessionBagInterface; Chris@0: Chris@0: /** Chris@0: * MockArraySessionStorage mocks the session for unit tests. Chris@0: * Chris@0: * No PHP session is actually started since a session can be initialized Chris@0: * and shutdown only once per PHP execution cycle. Chris@0: * Chris@0: * When doing functional testing, you should use MockFileSessionStorage instead. Chris@0: * Chris@0: * @author Fabien Potencier Chris@0: * @author Bulat Shakirzyanov Chris@0: * @author Drak Chris@0: */ Chris@0: class MockArraySessionStorage implements SessionStorageInterface Chris@0: { Chris@0: /** Chris@0: * @var string Chris@0: */ Chris@0: protected $id = ''; Chris@0: Chris@0: /** Chris@0: * @var string Chris@0: */ Chris@0: protected $name; Chris@0: Chris@0: /** Chris@0: * @var bool Chris@0: */ Chris@0: protected $started = false; Chris@0: Chris@0: /** Chris@0: * @var bool Chris@0: */ Chris@0: protected $closed = false; Chris@0: Chris@0: /** Chris@0: * @var array Chris@0: */ Chris@17: protected $data = []; Chris@0: Chris@0: /** Chris@0: * @var MetadataBag Chris@0: */ Chris@0: protected $metadataBag; Chris@0: Chris@0: /** Chris@0: * @var array|SessionBagInterface[] Chris@0: */ Chris@17: protected $bags = []; Chris@0: Chris@0: /** Chris@0: * @param string $name Session name Chris@0: * @param MetadataBag $metaBag MetadataBag instance Chris@0: */ Chris@0: public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null) Chris@0: { Chris@0: $this->name = $name; Chris@0: $this->setMetadataBag($metaBag); Chris@0: } Chris@0: Chris@0: public function setSessionData(array $array) Chris@0: { Chris@0: $this->data = $array; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function start() Chris@0: { Chris@0: if ($this->started) { Chris@0: return true; Chris@0: } Chris@0: Chris@0: if (empty($this->id)) { Chris@0: $this->id = $this->generateId(); Chris@0: } Chris@0: Chris@0: $this->loadSession(); Chris@0: Chris@0: return true; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function regenerate($destroy = false, $lifetime = null) Chris@0: { Chris@0: if (!$this->started) { Chris@0: $this->start(); Chris@0: } Chris@0: Chris@0: $this->metadataBag->stampNew($lifetime); Chris@0: $this->id = $this->generateId(); Chris@0: Chris@0: return true; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getId() Chris@0: { Chris@0: return $this->id; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function setId($id) Chris@0: { Chris@0: if ($this->started) { Chris@0: throw new \LogicException('Cannot set session ID after the session has started.'); Chris@0: } Chris@0: Chris@0: $this->id = $id; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getName() Chris@0: { Chris@0: return $this->name; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function setName($name) Chris@0: { Chris@0: $this->name = $name; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function save() Chris@0: { Chris@0: if (!$this->started || $this->closed) { Chris@0: throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); Chris@0: } Chris@0: // nothing to do since we don't persist the session data Chris@0: $this->closed = false; Chris@0: $this->started = false; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function clear() Chris@0: { Chris@0: // clear out the bags Chris@0: foreach ($this->bags as $bag) { Chris@0: $bag->clear(); Chris@0: } Chris@0: Chris@0: // clear out the session Chris@17: $this->data = []; Chris@0: Chris@0: // reconnect the bags to the session Chris@0: $this->loadSession(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function registerBag(SessionBagInterface $bag) Chris@0: { Chris@0: $this->bags[$bag->getName()] = $bag; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getBag($name) Chris@0: { Chris@0: if (!isset($this->bags[$name])) { Chris@0: throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); Chris@0: } Chris@0: Chris@0: if (!$this->started) { Chris@0: $this->start(); Chris@0: } Chris@0: Chris@0: return $this->bags[$name]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function isStarted() Chris@0: { Chris@0: return $this->started; Chris@0: } Chris@0: Chris@0: public function setMetadataBag(MetadataBag $bag = null) Chris@0: { Chris@0: if (null === $bag) { Chris@0: $bag = new MetadataBag(); Chris@0: } Chris@0: Chris@0: $this->metadataBag = $bag; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the MetadataBag. Chris@0: * Chris@0: * @return MetadataBag Chris@0: */ Chris@0: public function getMetadataBag() Chris@0: { Chris@0: return $this->metadataBag; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Generates a session ID. Chris@0: * Chris@0: * This doesn't need to be particularly cryptographically secure since this is just Chris@0: * a mock. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function generateId() Chris@0: { Chris@0: return hash('sha256', uniqid('ss_mock_', true)); Chris@0: } Chris@0: Chris@0: protected function loadSession() Chris@0: { Chris@17: $bags = array_merge($this->bags, [$this->metadataBag]); Chris@0: Chris@0: foreach ($bags as $bag) { Chris@0: $key = $bag->getStorageKey(); Chris@17: $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : []; Chris@0: $bag->initialize($this->data[$key]); Chris@0: } Chris@0: Chris@0: $this->started = true; Chris@0: $this->closed = false; Chris@0: } Chris@0: }