diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index bc21b5f730..4a5e63989a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -19,85 +19,55 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; class MemcacheSessionHandler implements \SessionHandlerInterface { /** - * Memcache driver. - * - * @var \Memcache + * @var \Memcache Memcache driver. */ private $memcache; /** - * Configuration options. - * - * @var array + * @var integer Time to live in seconds */ - private $memcacheOptions; + private $ttl; /** - * Key prefix for shared environments. - * - * @var string + * @var string Key prefix for shared environments. */ private $prefix; /** * Constructor. * - * @param \Memcache $memcache A \Memcache instance - * @param array $memcacheOptions An associative array of Memcache options - * @param array $options Session configuration options. + * List of available options: + * * prefix: The prefix to use for the memcache keys in order to avoid collision + * * expiretime: The time to live in seconds + * + * @param \Memcache $memcache A \Memcache instance + * @param array $options An associative array of Memcache options + * + * @throws \InvalidArgumentException When unsupported options are passed */ - public function __construct(\Memcache $memcache, array $memcacheOptions = array(), array $options = array()) + public function __construct(\Memcache $memcache, array $options = array()) { - $this->memcache = $memcache; - - // defaults - if (!isset($memcacheOptions['serverpool'])) { - $memcacheOptions['serverpool'] = array(array( - 'host' => '127.0.0.1', - 'port' => 11211, - 'timeout' => 1, - 'persistent' => false, - 'weight' => 1, - 'retry_interval' => 15, + if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { + throw new \InvalidArgumentException(sprintf( + 'The following options are not supported "%s"', implode(', ', $diff) )); } - $memcacheOptions['expiretime'] = isset($memcacheOptions['expiretime']) ? (int)$memcacheOptions['expiretime'] : 86400; - $this->prefix = isset($memcacheOptions['prefix']) ? $memcacheOptions['prefix'] : 'sf2s'; - - $this->memcacheOptions = $memcacheOptions; - } - - protected function addServer(array $server) - { - if (!array_key_exists('host', $server)) { - throw new \InvalidArgumentException('host key must be set'); - } - - $server['port'] = isset($server['port']) ? (int)$server['port'] : 11211; - $server['timeout'] = isset($server['timeout']) ? (int)$server['timeout'] : 1; - $server['persistent'] = isset($server['persistent']) ? (bool)$server['persistent'] : false; - $server['weight'] = isset($server['weight']) ? (int)$server['weight'] : 1; - $server['retry_interval'] = isset($server['retry_interval']) ? (int)$server['retry_interval'] : 15; - - $this->memcache->addserver($server['host'], $server['port'], $server['persistent'],$server['weight'],$server['timeout'],$server['retry_interval']); - + $this->memcache = $memcache; + $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; + $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; } /** - * {@inheritdoc} + * {@inheritDoc} */ public function open($savePath, $sessionName) { - foreach ($this->memcacheOptions['serverpool'] as $server) { - $this->addServer($server); - } - return true; } /** - * {@inheritdoc} + * {@inheritDoc} */ public function close() { @@ -105,7 +75,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function read($sessionId) { @@ -113,19 +83,15 @@ class MemcacheSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function write($sessionId, $data) { - if (!$this->memcache->replace($this->prefix.$sessionId, $data, 0, $this->memcacheOptions['expiretime'])) { - return $this->memcache->set($this->prefix.$sessionId, $data, 0, $this->memcacheOptions['expiretime']); - } - - return true; + return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl); } /** - * {@inheritdoc} + * {@inheritDoc} */ public function destroy($sessionId) { @@ -133,7 +99,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function gc($lifetime) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index 71770dda83..b666199a45 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -24,55 +24,57 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; class MemcachedSessionHandler implements \SessionHandlerInterface { /** - * Memcached driver. - * - * @var \Memcached + * @var \Memcached Memcached driver. */ private $memcached; /** - * Configuration options. - * - * @var array + * @var integer Time to live in seconds */ - private $memcachedOptions; + private $ttl; + + + /** + * @var string Key prefix for shared environments. + */ + private $prefix; /** * Constructor. * - * @param \Memcached $memcached A \Memcached instance - * @param array $memcachedOptions An associative array of Memcached options - * @param array $options Session configuration options. + * List of available options: + * * prefix: The prefix to use for the memcached keys in order to avoid collision + * * expiretime: The time to live in seconds + * + * @param \Memcached $memcached A \Memcached instance + * @param array $options An associative array of Memcached options + * + * @throws \InvalidArgumentException When unsupported options are passed */ - public function __construct(\Memcached $memcached, array $memcachedOptions = array(), array $options = array()) + public function __construct(\Memcached $memcached, array $options = array()) { $this->memcached = $memcached; - // defaults - if (!isset($memcachedOptions['serverpool'])) { - $memcachedOptions['serverpool'][] = array( - 'host' => '127.0.0.1', - 'port' => 11211, - 'weight' => 1); + if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { + throw new \InvalidArgumentException(sprintf( + 'The following options are not supported "%s"', implode(', ', $diff) + )); } - $memcachedOptions['expiretime'] = isset($memcachedOptions['expiretime']) ? (int)$memcachedOptions['expiretime'] : 86400; - - $this->memcached->setOption(\Memcached::OPT_PREFIX_KEY, isset($memcachedOptions['prefix']) ? $memcachedOptions['prefix'] : 'sf2s'); - - $this->memcachedOptions = $memcachedOptions; + $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; + $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; } /** - * {@inheritdoc} + * {@inheritDoc} */ public function open($savePath, $sessionName) { - return $this->memcached->addServers($this->memcachedOptions['serverpool']); + return true; } /** - * {@inheritdoc} + * {@inheritDoc} */ public function close() { @@ -80,51 +82,35 @@ class MemcachedSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function read($sessionId) { - return $this->memcached->get($sessionId) ?: ''; + return $this->memcached->get($this->prefix.$sessionId) ?: ''; } /** - * {@inheritdoc} + * {@inheritDoc} */ public function write($sessionId, $data) { - return $this->memcached->set($sessionId, $data, $this->memcachedOptions['expiretime']); + return $this->memcached->set($this->prefix.$sessionId, $data, time() + $this->ttl); } /** - * {@inheritdoc} + * {@inheritDoc} */ public function destroy($sessionId) { - return $this->memcached->delete($sessionId); + return $this->memcached->delete($this->prefix.$sessionId); } /** - * {@inheritdoc} + * {@inheritDoc} */ public function gc($lifetime) { // not required here because memcached will auto expire the records anyhow. return true; } - - /** - * Adds a server to the memcached handler. - * - * @param array $server - */ - protected function addServer(array $server) - { - if (array_key_exists('host', $server)) { - throw new \InvalidArgumentException('host key must be set'); - } - $server['port'] = isset($server['port']) ? (int)$server['port'] : 11211; - $server['timeout'] = isset($server['timeout']) ? (int)$server['timeout'] : 1; - $server['presistent'] = isset($server['presistent']) ? (bool)$server['presistent'] : false; - $server['weight'] = isset($server['weight']) ? (bool)$server['weight'] : 1; - } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 28dccba801..54b5e65a16 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -39,11 +39,10 @@ class PdoSessionHandler implements \SessionHandlerInterface * * @param \PDO $pdo A \PDO instance * @param array $dbOptions An associative array of DB options - * @param array $options Session configuration options * * @throws \InvalidArgumentException When "db_table" option is not provided */ - public function __construct(\PDO $pdo, array $dbOptions = array(), array $options = array()) + public function __construct(\PDO $pdo, array $dbOptions = array()) { if (!array_key_exists('db_table', $dbOptions)) { throw new \InvalidArgumentException('You must provide the "db_table" option for a PdoSessionStorage.'); @@ -58,7 +57,7 @@ class PdoSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function open($path, $name) { @@ -66,7 +65,7 @@ class PdoSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function close() { @@ -74,12 +73,12 @@ class PdoSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function destroy($id) { // get table/column - $dbTable = $this->dbOptions['db_table']; + $dbTable = $this->dbOptions['db_table']; $dbIdCol = $this->dbOptions['db_id_col']; // delete the record associated with this id @@ -97,20 +96,20 @@ class PdoSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function gc($lifetime) { // get table/column - $dbTable = $this->dbOptions['db_table']; + $dbTable = $this->dbOptions['db_table']; $dbTimeCol = $this->dbOptions['db_time_col']; // delete the session records that have expired - $sql = "DELETE FROM $dbTable WHERE $dbTimeCol < (:time - $lifetime)"; + $sql = "DELETE FROM $dbTable WHERE $dbTimeCol < :time"; try { $stmt = $this->pdo->prepare($sql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + $stmt->bindValue(':time', time() - $lifetime, \PDO::PARAM_INT); $stmt->execute(); } catch (\PDOException $e) { throw new \RuntimeException(sprintf('PDOException was thrown when trying to manipulate session data: %s', $e->getMessage()), 0, $e); @@ -120,12 +119,12 @@ class PdoSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function read($id) { // get table/columns - $dbTable = $this->dbOptions['db_table']; + $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; @@ -154,7 +153,7 @@ class PdoSessionHandler implements \SessionHandlerInterface } /** - * {@inheritdoc} + * {@inheritDoc} */ public function write($id, $data) { @@ -201,7 +200,7 @@ class PdoSessionHandler implements \SessionHandlerInterface private function createNewSession($id, $data = '') { // get table/column - $dbTable = $this->dbOptions['db_table']; + $dbTable = $this->dbOptions['db_table']; $dbDataCol = $this->dbOptions['db_data_col']; $dbIdCol = $this->dbOptions['db_id_col']; $dbTimeCol = $this->dbOptions['db_time_col']; diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php index 49e1568a09..da0440d428 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php @@ -15,6 +15,8 @@ use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHand class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase { + const PREFIX = 'prefix_'; + const TTL = 1000; /** * @var MemcacheSessionHandler */ @@ -29,7 +31,10 @@ class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase } $this->memcache = $this->getMock('Memcache'); - $this->storage = new MemcacheSessionHandler($this->memcache); + $this->storage = new MemcacheSessionHandler( + $this->memcache, + array('prefix' => self::PREFIX, 'expiretime' => self::TTL) + ); } protected function tearDown() @@ -40,82 +45,53 @@ class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase public function testOpenSession() { - $this->memcache->expects($this->atLeastOnce()) - ->method('addServer') - ->with('127.0.0.1', 11211, false, 1, 1, 15); - $this->assertTrue($this->storage->open('', '')); } - public function testConstructingWithServerPool() - { - $mock = $this->getMock('Memcache'); - - $storage = new MemcacheSessionHandler($mock, array( - 'serverpool' => array( - array('host' => '127.0.0.2'), - array('host' => '127.0.0.3', - 'port' => 11212, - 'timeout' => 10, - 'persistent' => true, - 'weight' => 5, - 'retry_interval' => 39, - ), - array('host' => '127.0.0.4', - 'port' => 11211, - 'weight' => 2 - ), - ), - )); - - $matcher = $mock - ->expects($this->at(0)) - ->method('addServer') - ->with('127.0.0.2', 11211, false, 1, 1, 15); - $matcher = $mock - ->expects($this->at(1)) - ->method('addServer') - ->with('127.0.0.3', 11212, true, 5, 10, 39); - $matcher = $mock - ->expects($this->at(2)) - ->method('addServer') - ->with('127.0.0.4', 11211, false, 2, 1, 15); - $this->assertTrue($storage->open('', '')); - } - public function testCloseSession() { - $this->memcache->expects($this->once()) + $this->memcache + ->expects($this->once()) ->method('close') - ->will($this->returnValue(true)); + ->will($this->returnValue(true)) + ; $this->assertTrue($this->storage->close()); } public function testReadSession() { - $this->memcache->expects($this->once()) - ->method('get'); + $this->memcache + ->expects($this->once()) + ->method('get') + ->with(self::PREFIX.'id') + ; - $this->assertEquals('', $this->storage->read('')); + $this->assertEquals('', $this->storage->read('id')); } public function testWriteSession() { - $this->memcache->expects($this->once()) + $this->memcache + ->expects($this->once()) ->method('set') - ->will($this->returnValue(true)); + ->with(self::PREFIX.'id', 'data', 0, $this->equalTo(time() + self::TTL, 2)) + ->will($this->returnValue(true)) + ; - $this->assertTrue($this->storage->write('', '')); + $this->assertTrue($this->storage->write('id', 'data')); } public function testDestroySession() { - $this->memcache->expects($this->once()) + $this->memcache + ->expects($this->once()) ->method('delete') - ->will($this->returnValue(true)); + ->with(self::PREFIX.'id') + ->will($this->returnValue(true)) + ; - $this->assertTrue($this->storage->destroy('')); + $this->assertTrue($this->storage->destroy('id')); } public function testGcSession() @@ -123,4 +99,26 @@ class MemcacheSessionHandlerTest extends \PHPUnit_Framework_TestCase $this->assertTrue($this->storage->gc(123)); } + /** + * @dataProvider getOptionFixtures + */ + public function testSupportedOptions($options, $supported) + { + try { + new MemcacheSessionHandler($this->memcache, $options); + $this->assertTrue($supported); + } catch (\InvalidArgumentException $e) { + $this->assertFalse($supported); + } + } + + public function getOptionFixtures() + { + return array( + array(array('prefix' => 'session'), true), + array(array('expiretime' => 100), true), + array(array('prefix' => 'session', 'expiretime' => 200), true), + array(array('expiretime' => 100, 'foo' => 'bar'), false), + ); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php index 5731d92c22..6f158cd1b7 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -15,6 +15,9 @@ use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHan class MemcacheddSessionHandlerTest extends \PHPUnit_Framework_TestCase { + const PREFIX = 'prefix_'; + const TTL = 1000; + /** * @var MemcachedSessionHandler */ @@ -29,7 +32,10 @@ class MemcacheddSessionHandlerTest extends \PHPUnit_Framework_TestCase } $this->memcached = $this->getMock('Memcached'); - $this->storage = new MemcachedSessionHandler($this->memcached); + $this->storage = new MemcachedSessionHandler( + $this->memcached, + array('prefix' => self::PREFIX, 'expiretime' => self::TTL) + ); } protected function tearDown() @@ -40,10 +46,6 @@ class MemcacheddSessionHandlerTest extends \PHPUnit_Framework_TestCase public function testOpenSession() { - $this->memcached->expects($this->atLeastOnce()) - ->method('addServers') - ->will($this->returnValue(true)); - $this->assertTrue($this->storage->open('', '')); } @@ -54,28 +56,37 @@ class MemcacheddSessionHandlerTest extends \PHPUnit_Framework_TestCase public function testReadSession() { - $this->memcached->expects($this->once()) - ->method('get'); + $this->memcached + ->expects($this->once()) + ->method('get') + ->with(self::PREFIX.'id') + ; - $this->assertEquals('', $this->storage->read('')); + $this->assertEquals('', $this->storage->read('id')); } public function testWriteSession() { - $this->memcached->expects($this->once()) + $this->memcached + ->expects($this->once()) ->method('set') - ->will($this->returnValue(true)); + ->with(self::PREFIX.'id', 'data', $this->equalTo(time() + self::TTL, 2)) + ->will($this->returnValue(true)) + ; - $this->assertTrue($this->storage->write('', '')); + $this->assertTrue($this->storage->write('id', 'data')); } public function testDestroySession() { - $this->memcached->expects($this->once()) + $this->memcached + ->expects($this->once()) ->method('delete') - ->will($this->returnValue(true)); + ->with(self::PREFIX.'id') + ->will($this->returnValue(true)) + ; - $this->assertTrue($this->storage->destroy('')); + $this->assertTrue($this->storage->destroy('id')); } public function testGcSession() @@ -83,5 +94,26 @@ class MemcacheddSessionHandlerTest extends \PHPUnit_Framework_TestCase $this->assertTrue($this->storage->gc(123)); } + /** + * @dataProvider getOptionFixtures + */ + public function testSupportedOptions($options, $supported) + { + try { + new MemcachedSessionHandler($this->memcached, $options); + $this->assertTrue($supported); + } catch (\InvalidArgumentException $e) { + $this->assertFalse($supported); + } + } + public function getOptionFixtures() + { + return array( + array(array('prefix' => 'session'), true), + array(array('expiretime' => 100), true), + array(array('prefix' => 'session', 'expiretime' => 200), true), + array(array('expiretime' => 100, 'foo' => 'bar'), false), + ); + } }