1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 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: use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
17: use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
18: use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
19:
20: 21: 22: 23: 24:
25: class NativeSessionStorage implements SessionStorageInterface
26: {
27: 28: 29: 30: 31:
32: protected $bags;
33:
34: 35: 36:
37: protected $started = false;
38:
39: 40: 41:
42: protected $closed = false;
43:
44: 45: 46:
47: protected $saveHandler;
48:
49: 50: 51:
52: protected $metadataBag;
53:
54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97:
98: public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
99: {
100: ini_set('session.cache_limiter', '');
101: ini_set('session.use_cookies', 1);
102:
103: if (version_compare(phpversion(), '5.4.0', '>=')) {
104: session_register_shutdown();
105: } else {
106: register_shutdown_function('session_write_close');
107: }
108:
109: $this->setMetadataBag($metaBag);
110: $this->setOptions($options);
111: $this->setSaveHandler($handler);
112: }
113:
114: 115: 116: 117: 118:
119: public function getSaveHandler()
120: {
121: return $this->saveHandler;
122: }
123:
124: 125: 126:
127: public function start()
128: {
129: if ($this->started && !$this->closed) {
130: return true;
131: }
132:
133:
134: if (!$this->started && !$this->closed && $this->saveHandler->isActive()
135: && $this->saveHandler->isSessionHandlerInterface()) {
136: $this->loadSession();
137:
138: return true;
139: }
140:
141: if (ini_get('session.use_cookies') && headers_sent()) {
142: throw new \RuntimeException('Failed to start the session because headers have already been sent.');
143: }
144:
145:
146: if (!session_start()) {
147: throw new \RuntimeException('Failed to start the session');
148: }
149:
150: $this->loadSession();
151:
152: if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
153: $this->saveHandler->setActive(false);
154: }
155:
156: return true;
157: }
158:
159: 160: 161:
162: public function getId()
163: {
164: if (!$this->started) {
165: return '';
166: }
167:
168: return $this->saveHandler->getId();
169: }
170:
171: 172: 173:
174: public function setId($id)
175: {
176: $this->saveHandler->setId($id);
177: }
178:
179: 180: 181:
182: public function getName()
183: {
184: return $this->saveHandler->getName();
185: }
186:
187: 188: 189:
190: public function setName($name)
191: {
192: $this->saveHandler->setName($name);
193: }
194:
195: 196: 197:
198: public function regenerate($destroy = false, $lifetime = null)
199: {
200: if (null !== $lifetime) {
201: ini_set('session.cookie_lifetime', $lifetime);
202: }
203:
204: if ($destroy) {
205: $this->metadataBag->stampNew();
206: }
207:
208: return session_regenerate_id($destroy);
209: }
210:
211: 212: 213:
214: public function save()
215: {
216: session_write_close();
217:
218: if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) {
219: $this->saveHandler->setActive(false);
220: }
221:
222: $this->closed = true;
223: }
224:
225: 226: 227:
228: public function clear()
229: {
230:
231: foreach ($this->bags as $bag) {
232: $bag->clear();
233: }
234:
235:
236: $_SESSION = array();
237:
238:
239: $this->loadSession();
240: }
241:
242: 243: 244:
245: public function registerBag(SessionBagInterface $bag)
246: {
247: $this->bags[$bag->getName()] = $bag;
248: }
249:
250: 251: 252:
253: public function getBag($name)
254: {
255: if (!isset($this->bags[$name])) {
256: throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
257: }
258:
259: if ($this->saveHandler->isActive() && !$this->started) {
260: $this->loadSession();
261: } elseif (!$this->started) {
262: $this->start();
263: }
264:
265: return $this->bags[$name];
266: }
267:
268: 269: 270: 271: 272:
273: public function setMetadataBag(MetadataBag $metaBag = null)
274: {
275: if (null === $metaBag) {
276: $metaBag = new MetadataBag();
277: }
278:
279: $this->metadataBag = $metaBag;
280: }
281:
282: 283: 284: 285: 286:
287: public function getMetadataBag()
288: {
289: return $this->metadataBag;
290: }
291:
292: 293: 294:
295: public function isStarted()
296: {
297: return $this->started;
298: }
299:
300: 301: 302: 303: 304: 305: 306: 307: 308: 309:
310: public function setOptions(array $options)
311: {
312: $validOptions = array_flip(array(
313: 'cache_limiter', 'cookie_domain', 'cookie_httponly',
314: 'cookie_lifetime', 'cookie_path', 'cookie_secure',
315: 'entropy_file', 'entropy_length', 'gc_divisor',
316: 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
317: 'hash_function', 'name', 'referer_check',
318: 'serialize_handler', 'use_cookies',
319: 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
320: 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
321: 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags',
322: ));
323:
324: foreach ($options as $key => $value) {
325: if (isset($validOptions[$key])) {
326: ini_set('session.'.$key, $value);
327: }
328: }
329: }
330:
331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345:
346: public function setSaveHandler($saveHandler = null)
347: {
348:
349: if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
350: $saveHandler = new SessionHandlerProxy($saveHandler);
351: } elseif (!$saveHandler instanceof AbstractProxy) {
352: $saveHandler = new NativeProxy();
353: }
354:
355: $this->saveHandler = $saveHandler;
356:
357: if ($this->saveHandler instanceof \SessionHandlerInterface) {
358: if (version_compare(phpversion(), '5.4.0', '>=')) {
359: session_set_save_handler($this->saveHandler, false);
360: } else {
361: session_set_save_handler(
362: array($this->saveHandler, 'open'),
363: array($this->saveHandler, 'close'),
364: array($this->saveHandler, 'read'),
365: array($this->saveHandler, 'write'),
366: array($this->saveHandler, 'destroy'),
367: array($this->saveHandler, 'gc')
368: );
369: }
370: }
371: }
372:
373: 374: 375: 376: 377: 378: 379: 380: 381: 382:
383: protected function loadSession(array &$session = null)
384: {
385: if (null === $session) {
386: $session = &$_SESSION;
387: }
388:
389: $bags = array_merge($this->bags, array($this->metadataBag));
390:
391: foreach ($bags as $bag) {
392: $key = $bag->getStorageKey();
393: $session[$key] = isset($session[$key]) ? $session[$key] : array();
394: $bag->initialize($session[$key]);
395: }
396:
397: $this->started = true;
398: $this->closed = false;
399: }
400: }
401: