[HttpFoundation] MongoDbSessionHandler supports auto expiry via configurable expiry_field
This commit is contained in:
parent
7f38207967
commit
beca900a61
@ -62,9 +62,10 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||||||
$this->mongo = $mongo;
|
$this->mongo = $mongo;
|
||||||
|
|
||||||
$this->options = array_merge(array(
|
$this->options = array_merge(array(
|
||||||
'id_field' => '_id',
|
'id_field' => '_id',
|
||||||
'data_field' => 'data',
|
'data_field' => 'data',
|
||||||
'time_field' => 'time',
|
'time_field' => 'time',
|
||||||
|
'expiry_field' => false,
|
||||||
), $options);
|
), $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +110,9 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||||||
*
|
*
|
||||||
* See: http://docs.mongodb.org/manual/tutorial/expire-data/
|
* See: http://docs.mongodb.org/manual/tutorial/expire-data/
|
||||||
*/
|
*/
|
||||||
|
if (false !== $this->options['expiry_field']) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
$time = new \MongoDate(time() - $maxlifetime);
|
$time = new \MongoDate(time() - $maxlifetime);
|
||||||
|
|
||||||
$this->getCollection()->remove(array(
|
$this->getCollection()->remove(array(
|
||||||
@ -123,12 +127,27 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||||||
*/
|
*/
|
||||||
public function write($sessionId, $data)
|
public function write($sessionId, $data)
|
||||||
{
|
{
|
||||||
|
$fields = array(
|
||||||
|
$this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY),
|
||||||
|
$this->options['time_field'] => new \MongoDate(),
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Note: As discussed in the gc method of this class. You can utilise
|
||||||
|
* TTL collections in MongoDB 2.2+
|
||||||
|
* We are setting the "expiry_field" as part of the write operation here
|
||||||
|
* You will need to create the index on your collection that expires documents
|
||||||
|
* at that time
|
||||||
|
* e.g.
|
||||||
|
* db.MySessionCollection.ensureIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
|
||||||
|
*/
|
||||||
|
if (false !== $this->options['expiry_field']) {
|
||||||
|
$expiry = new \MongoDate(time() + (int) ini_get('session.gc_maxlifetime'));
|
||||||
|
$fields[$this->options['expiry_field']] = $expiry;
|
||||||
|
}
|
||||||
|
|
||||||
$this->getCollection()->update(
|
$this->getCollection()->update(
|
||||||
array($this->options['id_field'] => $sessionId),
|
array($this->options['id_field'] => $sessionId),
|
||||||
array('$set' => array(
|
array('$set' => $fields),
|
||||||
$this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY),
|
|
||||||
$this->options['time_field'] => new \MongoDate(),
|
|
||||||
)),
|
|
||||||
array('upsert' => true, 'multiple' => false)
|
array('upsert' => true, 'multiple' => false)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class MongoDbSessionHandlerTest extends \PHPUnit_Framework_TestCase
|
|||||||
'data_field' => 'data',
|
'data_field' => 'data',
|
||||||
'time_field' => 'time',
|
'time_field' => 'time',
|
||||||
'database' => 'sf2-test',
|
'database' => 'sf2-test',
|
||||||
'collection' => 'session-test'
|
'collection' => 'session-test',
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
|
$this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
|
||||||
@ -100,6 +100,45 @@ class MongoDbSessionHandlerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$that->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
|
$that->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testWriteWhenUsingExpiresField()
|
||||||
|
{
|
||||||
|
$this->options = array(
|
||||||
|
'id_field' => '_id',
|
||||||
|
'data_field' => 'data',
|
||||||
|
'time_field' => 'time',
|
||||||
|
'database' => 'sf2-test',
|
||||||
|
'collection' => 'session-test',
|
||||||
|
'expiry_field' => 'expiresAt'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
|
||||||
|
|
||||||
|
$collection = $this->createMongoCollectionMock();
|
||||||
|
|
||||||
|
$this->mongo->expects($this->once())
|
||||||
|
->method('selectCollection')
|
||||||
|
->with($this->options['database'], $this->options['collection'])
|
||||||
|
->will($this->returnValue($collection));
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
$data = array();
|
||||||
|
|
||||||
|
$collection->expects($this->once())
|
||||||
|
->method('update')
|
||||||
|
->will($this->returnCallback(function ($criteria, $updateData, $options) use ($that, &$data) {
|
||||||
|
$that->assertEquals(array($that->options['id_field'] => 'foo'), $criteria);
|
||||||
|
$that->assertEquals(array('upsert' => true, 'multiple' => false), $options);
|
||||||
|
|
||||||
|
$data = $updateData['$set'];
|
||||||
|
}));
|
||||||
|
|
||||||
|
$this->assertTrue($this->storage->write('foo', 'bar'));
|
||||||
|
|
||||||
|
$this->assertEquals('bar', $data[$this->options['data_field']]->bin);
|
||||||
|
$that->assertInstanceOf('MongoDate', $data[$this->options['time_field']]);
|
||||||
|
$that->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]);
|
||||||
|
}
|
||||||
|
|
||||||
public function testReplaceSessionData()
|
public function testReplaceSessionData()
|
||||||
{
|
{
|
||||||
$collection = $this->createMongoCollectionMock();
|
$collection = $this->createMongoCollectionMock();
|
||||||
@ -154,10 +193,36 @@ class MongoDbSessionHandlerTest extends \PHPUnit_Framework_TestCase
|
|||||||
->method('remove')
|
->method('remove')
|
||||||
->will($this->returnCallback(function ($criteria) use ($that) {
|
->will($this->returnCallback(function ($criteria) use ($that) {
|
||||||
$that->assertInstanceOf('MongoDate', $criteria[$that->options['time_field']]['$lt']);
|
$that->assertInstanceOf('MongoDate', $criteria[$that->options['time_field']]['$lt']);
|
||||||
$that->assertGreaterThanOrEqual(time() - -1, $criteria[$that->options['time_field']]['$lt']->sec);
|
$that->assertGreaterThanOrEqual(time() - 1, $criteria[$that->options['time_field']]['$lt']->sec);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$this->assertTrue($this->storage->gc(-1));
|
$this->assertTrue($this->storage->gc(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGcWhenUsingExpiresField()
|
||||||
|
{
|
||||||
|
$this->options = array(
|
||||||
|
'id_field' => '_id',
|
||||||
|
'data_field' => 'data',
|
||||||
|
'time_field' => 'time',
|
||||||
|
'database' => 'sf2-test',
|
||||||
|
'collection' => 'session-test',
|
||||||
|
'expiry_field' => 'expiresAt'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->storage = new MongoDbSessionHandler($this->mongo, $this->options);
|
||||||
|
|
||||||
|
$collection = $this->createMongoCollectionMock();
|
||||||
|
|
||||||
|
$this->mongo->expects($this->never())
|
||||||
|
->method('selectCollection');
|
||||||
|
|
||||||
|
$that = $this;
|
||||||
|
|
||||||
|
$collection->expects($this->never())
|
||||||
|
->method('remove');
|
||||||
|
|
||||||
|
$this->assertTrue($this->storage->gc(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetConnection()
|
public function testGetConnection()
|
||||||
|
Reference in New Issue
Block a user