Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\HttpFoundation\Session\Storage;
|
Chris@0
|
13
|
Chris@0
|
14 /**
|
Chris@0
|
15 * MockFileSessionStorage is used to mock sessions for
|
Chris@0
|
16 * functional testing when done in a single PHP process.
|
Chris@0
|
17 *
|
Chris@0
|
18 * No PHP session is actually started since a session can be initialized
|
Chris@0
|
19 * and shutdown only once per PHP execution cycle and this class does
|
Chris@0
|
20 * not pollute any session related globals, including session_*() functions
|
Chris@0
|
21 * or session.* PHP ini directives.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @author Drak <drak@zikula.org>
|
Chris@0
|
24 */
|
Chris@0
|
25 class MockFileSessionStorage extends MockArraySessionStorage
|
Chris@0
|
26 {
|
Chris@0
|
27 private $savePath;
|
Chris@0
|
28
|
Chris@0
|
29 /**
|
Chris@0
|
30 * @param string $savePath Path of directory to save session files
|
Chris@0
|
31 * @param string $name Session name
|
Chris@0
|
32 * @param MetadataBag $metaBag MetadataBag instance
|
Chris@0
|
33 */
|
Chris@0
|
34 public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null)
|
Chris@0
|
35 {
|
Chris@0
|
36 if (null === $savePath) {
|
Chris@0
|
37 $savePath = sys_get_temp_dir();
|
Chris@0
|
38 }
|
Chris@0
|
39
|
Chris@0
|
40 if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) {
|
Chris@0
|
41 throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath));
|
Chris@0
|
42 }
|
Chris@0
|
43
|
Chris@0
|
44 $this->savePath = $savePath;
|
Chris@0
|
45
|
Chris@0
|
46 parent::__construct($name, $metaBag);
|
Chris@0
|
47 }
|
Chris@0
|
48
|
Chris@0
|
49 /**
|
Chris@0
|
50 * {@inheritdoc}
|
Chris@0
|
51 */
|
Chris@0
|
52 public function start()
|
Chris@0
|
53 {
|
Chris@0
|
54 if ($this->started) {
|
Chris@0
|
55 return true;
|
Chris@0
|
56 }
|
Chris@0
|
57
|
Chris@0
|
58 if (!$this->id) {
|
Chris@0
|
59 $this->id = $this->generateId();
|
Chris@0
|
60 }
|
Chris@0
|
61
|
Chris@0
|
62 $this->read();
|
Chris@0
|
63
|
Chris@0
|
64 $this->started = true;
|
Chris@0
|
65
|
Chris@0
|
66 return true;
|
Chris@0
|
67 }
|
Chris@0
|
68
|
Chris@0
|
69 /**
|
Chris@0
|
70 * {@inheritdoc}
|
Chris@0
|
71 */
|
Chris@0
|
72 public function regenerate($destroy = false, $lifetime = null)
|
Chris@0
|
73 {
|
Chris@0
|
74 if (!$this->started) {
|
Chris@0
|
75 $this->start();
|
Chris@0
|
76 }
|
Chris@0
|
77
|
Chris@0
|
78 if ($destroy) {
|
Chris@0
|
79 $this->destroy();
|
Chris@0
|
80 }
|
Chris@0
|
81
|
Chris@0
|
82 return parent::regenerate($destroy, $lifetime);
|
Chris@0
|
83 }
|
Chris@0
|
84
|
Chris@0
|
85 /**
|
Chris@0
|
86 * {@inheritdoc}
|
Chris@0
|
87 */
|
Chris@0
|
88 public function save()
|
Chris@0
|
89 {
|
Chris@0
|
90 if (!$this->started) {
|
Chris@0
|
91 throw new \RuntimeException('Trying to save a session that was not started yet or was already closed');
|
Chris@0
|
92 }
|
Chris@0
|
93
|
Chris@14
|
94 $data = $this->data;
|
Chris@14
|
95
|
Chris@14
|
96 foreach ($this->bags as $bag) {
|
Chris@14
|
97 if (empty($data[$key = $bag->getStorageKey()])) {
|
Chris@14
|
98 unset($data[$key]);
|
Chris@14
|
99 }
|
Chris@14
|
100 }
|
Chris@17
|
101 if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) {
|
Chris@14
|
102 unset($data[$key]);
|
Chris@14
|
103 }
|
Chris@14
|
104
|
Chris@14
|
105 try {
|
Chris@14
|
106 if ($data) {
|
Chris@14
|
107 file_put_contents($this->getFilePath(), serialize($data));
|
Chris@14
|
108 } else {
|
Chris@14
|
109 $this->destroy();
|
Chris@14
|
110 }
|
Chris@14
|
111 } finally {
|
Chris@14
|
112 $this->data = $data;
|
Chris@14
|
113 }
|
Chris@0
|
114
|
Chris@0
|
115 // this is needed for Silex, where the session object is re-used across requests
|
Chris@0
|
116 // in functional tests. In Symfony, the container is rebooted, so we don't have
|
Chris@0
|
117 // this issue
|
Chris@0
|
118 $this->started = false;
|
Chris@0
|
119 }
|
Chris@0
|
120
|
Chris@0
|
121 /**
|
Chris@0
|
122 * Deletes a session from persistent storage.
|
Chris@0
|
123 * Deliberately leaves session data in memory intact.
|
Chris@0
|
124 */
|
Chris@0
|
125 private function destroy()
|
Chris@0
|
126 {
|
Chris@0
|
127 if (is_file($this->getFilePath())) {
|
Chris@0
|
128 unlink($this->getFilePath());
|
Chris@0
|
129 }
|
Chris@0
|
130 }
|
Chris@0
|
131
|
Chris@0
|
132 /**
|
Chris@0
|
133 * Calculate path to file.
|
Chris@0
|
134 *
|
Chris@0
|
135 * @return string File path
|
Chris@0
|
136 */
|
Chris@0
|
137 private function getFilePath()
|
Chris@0
|
138 {
|
Chris@0
|
139 return $this->savePath.'/'.$this->id.'.mocksess';
|
Chris@0
|
140 }
|
Chris@0
|
141
|
Chris@0
|
142 /**
|
Chris@0
|
143 * Reads session from storage and loads session.
|
Chris@0
|
144 */
|
Chris@0
|
145 private function read()
|
Chris@0
|
146 {
|
Chris@0
|
147 $filePath = $this->getFilePath();
|
Chris@17
|
148 $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : [];
|
Chris@0
|
149
|
Chris@0
|
150 $this->loadSession();
|
Chris@0
|
151 }
|
Chris@0
|
152 }
|