PluginProbe ʕ •ᴥ•ʔ
Transferito: WP Migration / trunk
Transferito: WP Migration vtrunk
trunk 11.4.0 12.0.0 13.1.0 14.0.0 14.0.11 14.0.7 14.1.0 14.1.1 14.1.2 14.1.3 14.1.4
transferito / vendor / aws / aws-sdk-php / src / DynamoDb / SessionHandler.php
transferito / vendor / aws / aws-sdk-php / src / DynamoDb Last commit date
Exception 11 months ago BinaryValue.php 11 months ago DynamoDbClient.php 11 months ago LockingSessionConnection.php 11 months ago Marshaler.php 11 months ago NumberValue.php 11 months ago SessionConnectionConfigTrait.php 11 months ago SessionConnectionInterface.php 11 months ago SessionHandler.php 11 months ago SetValue.php 11 months ago StandardSessionConnection.php 11 months ago WriteRequestBatch.php 11 months ago
SessionHandler.php
242 lines
1 <?php
2 namespace Aws\DynamoDb;
3
4 /**
5 * Provides an interface for using Amazon DynamoDB as a session store by hooking
6 * into PHP's session handler hooks. Once registered, You may use the native
7 * `$_SESSION` superglobal and session functions, and the sessions will be
8 * stored automatically in DynamoDB. DynamoDB is a great session storage
9 * solution due to its speed, scalability, and fault tolerance.
10 *
11 * For maximum performance, we recommend that you keep the size of your sessions
12 * small. Locking is disabled by default, since it can drive up latencies and
13 * costs under high traffic. Only turn it on if you need it.
14 *
15 * By far, the most expensive operation is garbage collection. Therefore, we
16 * encourage you to carefully consider your session garbage collection strategy.
17 * Note: the DynamoDB Session Handler does not allow garbage collection to be
18 * triggered randomly. You must run garbage collection manually or through other
19 * automated means using a cron job or similar scheduling technique.
20 */
21 class SessionHandler implements \SessionHandlerInterface
22 {
23 /** @var SessionConnectionInterface Session save logic.*/
24 private $connection;
25
26 /** @var string Session save path. */
27 private $savePath;
28
29 /** @var string Session name. */
30 private $sessionName;
31
32 /** @var string The last known session ID */
33 private $openSessionId = '';
34
35 /** @var string Stores serialized data for tracking changes. */
36 private $dataRead = '';
37
38 /** @var bool Keeps track of whether the session has been written. */
39 private $sessionWritten = false;
40
41 /**
42 * Creates a new DynamoDB Session Handler.
43 *
44 * The configuration array accepts the following array keys and values:
45 * - table_name: Name of table to store the sessions.
46 * - hash_key: Name of hash key in table. Default: "id".
47 * - data_attribute: Name of the data attribute in table. Default: "data".
48 * - session_lifetime: Lifetime of inactive sessions expiration.
49 * - session_lifetime_attribute: Name of the session life time attribute in table. Default: "expires".
50 * - consistent_read: Whether or not to use consistent reads.
51 * - batch_config: Batch options used for garbage collection.
52 * - locking: Whether or not to use session locking.
53 * - max_lock_wait_time: Max time (s) to wait for lock acquisition.
54 * - min_lock_retry_microtime: Min time (µs) to wait between lock attempts.
55 * - max_lock_retry_microtime: Max time (µs) to wait between lock attempts.
56 *
57 * You can find the full list of parameters and defaults within the trait
58 * Aws\DynamoDb\SessionConnectionConfigTrait
59 *
60 * @param DynamoDbClient $client Client for doing DynamoDB operations
61 * @param array $config Configuration for the Session Handler
62 *
63 * @return SessionHandler
64 */
65 public static function fromClient(DynamoDbClient $client, array $config = [])
66 {
67 $config += ['locking' => false];
68 if ($config['locking']) {
69 $connection = new LockingSessionConnection($client, $config);
70 } else {
71 $connection = new StandardSessionConnection($client, $config);
72 }
73
74 return new static($connection);
75 }
76
77 /**
78 * @param SessionConnectionInterface $connection
79 */
80 public function __construct(SessionConnectionInterface $connection)
81 {
82 $this->connection = $connection;
83 }
84
85 /**
86 * Register the DynamoDB session handler.
87 *
88 * @return bool Whether or not the handler was registered.
89 * @codeCoverageIgnore
90 */
91 public function register()
92 {
93 return session_set_save_handler($this, true);
94 }
95
96 /**
97 * Open a session for writing. Triggered by session_start().
98 *
99 * @param string $savePath Session save path.
100 * @param string $sessionName Session name.
101 *
102 * @return bool Whether or not the operation succeeded.
103 */
104 #[\ReturnTypeWillChange]
105 public function open($savePath, $sessionName)
106 {
107 $this->savePath = $savePath;
108 $this->sessionName = $sessionName;
109
110 return true;
111 }
112
113 /**
114 * Close a session from writing.
115 *
116 * @return bool Success
117 */
118 #[\ReturnTypeWillChange]
119 public function close()
120 {
121 $id = session_id();
122 // Make sure the session is unlocked and the expiration time is updated,
123 // even if the write did not occur
124 if ($this->openSessionId !== $id || !$this->sessionWritten) {
125 $result = $this->connection->write($this->formatId($id), '', false);
126 $this->sessionWritten = (bool) $result;
127 }
128
129 return $this->sessionWritten;
130 }
131
132 /**
133 * Read a session stored in DynamoDB.
134 *
135 * @param string $id Session ID.
136 *
137 * @return string Session data.
138 */
139 #[\ReturnTypeWillChange]
140 public function read($id)
141 {
142 $this->openSessionId = $id;
143 // PHP expects an empty string to be returned from this method if no
144 // data is retrieved
145 $this->dataRead = '';
146
147 // Get session data using the selected locking strategy
148 $item = $this->connection->read($this->formatId($id));
149
150 $dataAttribute = $this->connection->getDataAttribute();
151 $sessionLifetimeAttribute = $this->connection->getSessionLifetimeAttribute();
152
153 // Return the data if it is not expired. If it is expired, remove it
154 if (isset($item[$sessionLifetimeAttribute]) && isset($item[$dataAttribute])) {
155 $this->dataRead = $item[$dataAttribute];
156 if ($item[$sessionLifetimeAttribute] <= time()) {
157 $this->dataRead = '';
158 $this->destroy($id);
159 }
160 }
161
162 return $this->dataRead;
163 }
164
165 /**
166 * Write a session to DynamoDB.
167 *
168 * @param string $id Session ID.
169 * @param string $data Serialized session data to write.
170 *
171 * @return bool Whether or not the operation succeeded.
172 */
173 #[\ReturnTypeWillChange]
174 public function write($id, $data)
175 {
176 $changed = $id !== $this->openSessionId
177 || $data !== $this->dataRead;
178 $this->openSessionId = $id;
179
180 // Write the session data using the selected locking strategy
181 $this->sessionWritten = $this->connection
182 ->write($this->formatId($id), $data, $changed);
183
184 return $this->sessionWritten;
185 }
186
187 /**
188 * Delete a session stored in DynamoDB.
189 *
190 * @param string $id Session ID.
191 *
192 * @return bool Whether or not the operation succeeded.
193 */
194 #[\ReturnTypeWillChange]
195 public function destroy($id)
196 {
197 $this->openSessionId = $id;
198 // Delete the session data using the selected locking strategy
199 $this->sessionWritten
200 = $this->connection->delete($this->formatId($id));
201
202 return $this->sessionWritten;
203 }
204
205 /**
206 * Satisfies the session handler interface, but does nothing. To do garbage
207 * collection, you must manually call the garbageCollect() method.
208 *
209 * @param int $maxLifetime Ignored.
210 *
211 * @return bool Whether or not the operation succeeded.
212 * @codeCoverageIgnore
213 */
214 #[\ReturnTypeWillChange]
215 public function gc($maxLifetime)
216 {
217 // Garbage collection for a DynamoDB table must be triggered manually.
218 return true;
219 }
220
221 /**
222 * Triggers garbage collection on expired sessions.
223 * @codeCoverageIgnore
224 */
225 public function garbageCollect()
226 {
227 $this->connection->deleteExpired();
228 }
229
230 /**
231 * Prepend the session ID with the session name.
232 *
233 * @param string $id The session ID.
234 *
235 * @return string Prepared session ID.
236 */
237 private function formatId($id)
238 {
239 return trim($this->sessionName . '_' . $id, '_');
240 }
241 }
242