1: <?php
2:
3: /*
4: * This file is part of the Symfony package.
5: *
6: * (c) Fabien Potencier <fabien@symfony.com>
7: *
8: * For the full copyright and license information, please view the LICENSE
9: * file that was distributed with this source code.
10: */
11:
12: namespace Symfony\Component\HttpFoundation\Session\Storage;
13:
14: use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
15: use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
16:
17: /**
18: * MockArraySessionStorage mocks the session for unit tests.
19: *
20: * No PHP session is actually started since a session can be initialized
21: * and shutdown only once per PHP execution cycle.
22: *
23: * When doing functional testing, you should use MockFileSessionStorage instead.
24: *
25: * @author Fabien Potencier <fabien@symfony.com>
26: * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
27: * @author Drak <drak@zikula.org>
28: */
29: class MockArraySessionStorage implements SessionStorageInterface
30: {
31: /**
32: * @var string
33: */
34: protected $id = '';
35:
36: /**
37: * @var string
38: */
39: protected $name;
40:
41: /**
42: * @var boolean
43: */
44: protected $started = false;
45:
46: /**
47: * @var boolean
48: */
49: protected $closed = false;
50:
51: /**
52: * @var array
53: */
54: protected $data = array();
55:
56: /**
57: * @var MetadataBag
58: */
59: protected $metadataBag;
60:
61: /**
62: * @var array
63: */
64: protected $bags;
65:
66: /**
67: * Constructor.
68: *
69: * @param string $name Session name
70: * @param MetadataBag $metaBag MetadataBag instance.
71: */
72: public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null)
73: {
74: $this->name = $name;
75: $this->setMetadataBag($metaBag);
76: }
77:
78: /**
79: * Sets the session data.
80: *
81: * @param array $array
82: */
83: public function setSessionData(array $array)
84: {
85: $this->data = $array;
86: }
87:
88: /**
89: * {@inheritdoc}
90: */
91: public function start()
92: {
93: if ($this->started && !$this->closed) {
94: return true;
95: }
96:
97: if (empty($this->id)) {
98: $this->id = $this->generateId();
99: }
100:
101: $this->loadSession();
102:
103: return true;
104: }
105:
106: /**
107: * {@inheritdoc}
108: */
109: public function regenerate($destroy = false, $lifetime = null)
110: {
111: if (!$this->started) {
112: $this->start();
113: }
114:
115: $this->metadataBag->stampNew($lifetime);
116: $this->id = $this->generateId();
117:
118: return true;
119: }
120:
121: /**
122: * {@inheritdoc}
123: */
124: public function getId()
125: {
126: return $this->id;
127: }
128:
129: /**
130: * {@inheritdoc}
131: */
132: public function setId($id)
133: {
134: if ($this->started) {
135: throw new \LogicException('Cannot set session ID after the session has started.');
136: }
137:
138: $this->id = $id;
139: }
140:
141: /**
142: * {@inheritdoc}
143: */
144: public function getName()
145: {
146: return $this->name;
147: }
148:
149: /**
150: * {@inheritdoc}
151: */
152: public function setName($name)
153: {
154: $this->name = $name;
155: }
156:
157: /**
158: * {@inheritdoc}
159: */
160: public function save()
161: {
162: if (!$this->started || $this->closed) {
163: throw new \RuntimeException("Trying to save a session that was not started yet or was already closed");
164: }
165: // nothing to do since we don't persist the session data
166: $this->closed = false;
167: }
168:
169: /**
170: * {@inheritdoc}
171: */
172: public function clear()
173: {
174: // clear out the bags
175: foreach ($this->bags as $bag) {
176: $bag->clear();
177: }
178:
179: // clear out the session
180: $this->data = array();
181:
182: // reconnect the bags to the session
183: $this->loadSession();
184: }
185:
186: /**
187: * {@inheritdoc}
188: */
189: public function registerBag(SessionBagInterface $bag)
190: {
191: $this->bags[$bag->getName()] = $bag;
192: }
193:
194: /**
195: * {@inheritdoc}
196: */
197: public function getBag($name)
198: {
199: if (!isset($this->bags[$name])) {
200: throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
201: }
202:
203: if (!$this->started) {
204: $this->start();
205: }
206:
207: return $this->bags[$name];
208: }
209:
210: /**
211: * {@inheritdoc}
212: */
213: public function isStarted()
214: {
215: return $this->started;
216: }
217:
218: /**
219: * Sets the MetadataBag.
220: *
221: * @param MetadataBag $bag
222: */
223: public function setMetadataBag(MetadataBag $bag = null)
224: {
225: if (null === $bag) {
226: $bag = new MetadataBag();
227: }
228:
229: $this->metadataBag = $bag;
230: }
231:
232: /**
233: * Gets the MetadataBag.
234: *
235: * @return MetadataBag
236: */
237: public function getMetadataBag()
238: {
239: return $this->metadataBag;
240: }
241:
242: /**
243: * Generates a session ID.
244: *
245: * This doesn't need to be particularly cryptographically secure since this is just
246: * a mock.
247: *
248: * @return string
249: */
250: protected function generateId()
251: {
252: return sha1(uniqid(mt_rand()));
253: }
254:
255: protected function loadSession()
256: {
257: $bags = array_merge($this->bags, array($this->metadataBag));
258:
259: foreach ($bags as $bag) {
260: $key = $bag->getStorageKey();
261: $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array();
262: $bag->initialize($this->data[$key]);
263: }
264:
265: $this->started = true;
266: $this->closed = false;
267: }
268: }
269: