Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
MongoDbSessionHandler.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
013
014 /**
015 * Session handler using the mongodb/mongodb package and MongoDB driver extension.
016 *
017 * @author Markus Bachmann <markus.bachmann@bachi.biz>
018 *
019 * @see https://packagist.org/packages/mongodb/mongodb
020 * @see https://php.net/mongodb
021 */
022 class MongoDbSessionHandler extends AbstractSessionHandler
023 {
024 private $mongo;
025
026 /**
027 * @var \MongoCollection
028 */
029 private $collection;
030
031 /**
032 * @var array
033 */
034 private $options;
035
036 /**
037 * Constructor.
038 *
039 * List of available options:
040 * * database: The name of the database [required]
041 * * collection: The name of the collection [required]
042 * * id_field: The field name for storing the session id [default: _id]
043 * * data_field: The field name for storing the session data [default: data]
044 * * time_field: The field name for storing the timestamp [default: time]
045 * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at].
046 *
047 * It is strongly recommended to put an index on the `expiry_field` for
048 * garbage-collection. Alternatively it's possible to automatically expire
049 * the sessions in the database as described below:
050 *
051 * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions
052 * automatically. Such an index can for example look like this:
053 *
054 * db.<session-collection>.ensureIndex(
055 * { "<expiry-field>": 1 },
056 * { "expireAfterSeconds": 0 }
057 * )
058 *
059 * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/
060 *
061 * If you use such an index, you can drop `gc_probability` to 0 since
062 * no garbage-collection is required.
063 *
064 * @param \MongoDB\Client $mongo A MongoDB\Client instance
065 * @param array $options An associative array of field options
066 *
067 * @throws \InvalidArgumentException When MongoClient or Mongo instance not provided
068 * @throws \InvalidArgumentException When "database" or "collection" not provided
069 */
070 public function __construct($mongo, array $options)
071 {
072 if ($mongo instanceof \MongoClient || $mongo instanceof \Mongo) {
073 @trigger_error(sprintf('Using %s with the legacy mongo extension is deprecated as of 3.4 and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead.', __CLASS__), \E_USER_DEPRECATED);
074 }
075
076 if (!($mongo instanceof \MongoDB\Client || $mongo instanceof \MongoClient || $mongo instanceof \Mongo)) {
077 throw new \InvalidArgumentException('MongoClient or Mongo instance required.');
078 }
079
080 if (!isset($options['database']) || !isset($options['collection'])) {
081 throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.');
082 }
083
084 $this->mongo = $mongo;
085
086 $this->options = array_merge([
087 'id_field' => '_id',
088 'data_field' => 'data',
089 'time_field' => 'time',
090 'expiry_field' => 'expires_at',
091 ], $options);
092 }
093
094 /**
095 * {@inheritdoc}
096 */
097 public function close()
098 {
099 return true;
100 }
101
102 /**
103 * {@inheritdoc}
104 */
105 protected function doDestroy($sessionId)
106 {
107 $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove';
108
109 $this->getCollection()->$methodName([
110 $this->options['id_field'] => $sessionId,
111 ]);
112
113 return true;
114 }
115
116 /**
117 * {@inheritdoc}
118 */
119 public function gc($maxlifetime)
120 {
121 $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteMany' : 'remove';
122
123 $this->getCollection()->$methodName([
124 $this->options['expiry_field'] => ['$lt' => $this->createDateTime()],
125 ]);
126
127 return true;
128 }
129
130 /**
131 * {@inheritdoc}
132 */
133 protected function doWrite($sessionId, $data)
134 {
135 $expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime'));
136
137 $fields = [
138 $this->options['time_field'] => $this->createDateTime(),
139 $this->options['expiry_field'] => $expiry,
140 ];
141
142 $options = ['upsert' => true];
143
144 if ($this->mongo instanceof \MongoDB\Client) {
145 $fields[$this->options['data_field']] = new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY);
146 } else {
147 $fields[$this->options['data_field']] = new \MongoBinData($data, \MongoBinData::BYTE_ARRAY);
148 $options['multiple'] = false;
149 }
150
151 $methodName = $this->mongo instanceof \MongoDB\Client ? 'updateOne' : 'update';
152
153 $this->getCollection()->$methodName(
154 [$this->options['id_field'] => $sessionId],
155 ['$set' => $fields],
156 $options
157 );
158
159 return true;
160 }
161
162 /**
163 * {@inheritdoc}
164 */
165 public function updateTimestamp($sessionId, $data)
166 {
167 $expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime'));
168
169 if ($this->mongo instanceof \MongoDB\Client) {
170 $methodName = 'updateOne';
171 $options = [];
172 } else {
173 $methodName = 'update';
174 $options = ['multiple' => false];
175 }
176
177 $this->getCollection()->$methodName(
178 [$this->options['id_field'] => $sessionId],
179 ['$set' => [
180 $this->options['time_field'] => $this->createDateTime(),
181 $this->options['expiry_field'] => $expiry,
182 ]],
183 $options
184 );
185
186 return true;
187 }
188
189 /**
190 * {@inheritdoc}
191 */
192 protected function doRead($sessionId)
193 {
194 $dbData = $this->getCollection()->findOne([
195 $this->options['id_field'] => $sessionId,
196 $this->options['expiry_field'] => ['$gte' => $this->createDateTime()],
197 ]);
198
199 if (null === $dbData) {
200 return '';
201 }
202
203 if ($dbData[$this->options['data_field']] instanceof \MongoDB\BSON\Binary) {
204 return $dbData[$this->options['data_field']]->getData();
205 }
206
207 return $dbData[$this->options['data_field']]->bin;
208 }
209
210 /**
211 * Return a "MongoCollection" instance.
212 *
213 * @return \MongoCollection
214 */
215 private function getCollection()
216 {
217 if (null === $this->collection) {
218 $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']);
219 }
220
221 return $this->collection;
222 }
223
224 /**
225 * Return a Mongo instance.
226 *
227 * @return \Mongo|\MongoClient|\MongoDB\Client
228 */
229 protected function getMongo()
230 {
231 return $this->mongo;
232 }
233
234 /**
235 * Create a date object using the class appropriate for the current mongo connection.
236 *
237 * Return an instance of a MongoDate or \MongoDB\BSON\UTCDateTime
238 *
239 * @param int $seconds An integer representing UTC seconds since Jan 1 1970. Defaults to now.
240 *
241 * @return \MongoDate|\MongoDB\BSON\UTCDateTime
242 */
243 private function createDateTime($seconds = null)
244 {
245 if (null === $seconds) {
246 $seconds = time();
247 }
248
249 if ($this->mongo instanceof \MongoDB\Client) {
250 return new \MongoDB\BSON\UTCDateTime($seconds * 1000);
251 }
252
253 return new \MongoDate($seconds);
254 }
255 }
256