Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}