diff --git a/src/Symfony/Component/HttpFoundation/SessionStorage/MemcacheSessionStorage.php b/src/Symfony/Component/HttpFoundation/SessionStorage/MemcacheSessionStorage.php new file mode 100644 index 0000000000..e3d8d4c42b --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/SessionStorage/MemcacheSessionStorage.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\SessionStorage; + +use Symfony\Component\HttpFoundation\AttributeBagInterface; +use Symfony\Component\HttpFoundation\FlashBagInterface; + +/** + * MemcacheSessionStorage. + * + * @author Drak + */ +class MemcacheSessionStorage extends AbstractSessionStorage implements SessionSaveHandlerInterface +{ + /** + * Memcache driver. + * + * @var Memcache + */ + private $memcache; + + /** + * Configuration options. + * + * @var array + */ + private $memcacheOptions; + + /** + * Key prefix for shared environments. + * + * @var string + */ + private $prefix; + + /** + * Constructor. + * + * @param \Memcache $memcache A \Memcache instance + * @param array $memcacheOptions An associative array of Memcachge options + * @param array $options Session configuration options. + * @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag) + * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag) + * + * @see AbstractSessionStorage::__construct() + */ + public function __construct(\Memcache $memcache, array $memcacheOptions = array(), array $options = array(), AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) + { + $this->memcache = $memcache; + + // defaults + if (!isset($memcacheOptions['serverpool'])) { + $memcacheOptions['serverpool'] = array( + 'host' => '127.0.0.1', + 'port' => 11211, + 'timeout' => 1, + 'persistent' => false, + 'weight' => 1); + } + + $memcacheOptions['expiretime'] = isset($memcacheOptions['expiretime']) ? (int)$memcacheOptions['expiretime'] : 86400; + $this->prefix = isset($memcachedOptions['prefix']) ? $memcachedOptions['prefix'] : 'sf2s'; + + $this->memcacheOptions = $memcacheOptions; + + parent::__construct($attributes, $flashes, $options); + } + + 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; + } + + /** + * {@inheritdoc} + */ + public function sessionOpen($savePath, $sessionName) + { + foreach ($this->memcacheOptions['serverpool'] as $server) { + $this->addServer($server); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function sessionClose() + { + return $this->memcache->close(); + } + + /** + * {@inheritdoc} + */ + public function sessionRead($sessionId) + { + $result = $this->memcache->get($this->prefix.$sessionId); + + return ($result) ? $result : ''; + } + + /** + * {@inheritdoc} + */ + public function sessionWrite($sessionId, $data) + { + return $this->memcache->set($this->prefix.$sessionId, $data, $this->memcacheOptions['expiretime']); + } + + /** + * {@inheritdoc} + */ + public function sessionDestroy($sessionId) + { + return $this->memcache->delete($this->prefix.$sessionId); + } + + /** + * {@inheritdoc} + */ + public function sessionGc($lifetime) + { + // not required here because memcache will auto expire the records anyhow. + return true; + } +} diff --git a/src/Symfony/Component/HttpFoundation/SessionStorage/MemcachedSessionStorage.php b/src/Symfony/Component/HttpFoundation/SessionStorage/MemcachedSessionStorage.php new file mode 100644 index 0000000000..f91c7da6d5 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/SessionStorage/MemcachedSessionStorage.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\SessionStorage; + +use Symfony\Component\HttpFoundation\AttributeBagInterface; +use Symfony\Component\HttpFoundation\FlashBagInterface; + +/** + * MemcachedSessionStorage. + * + * @author Drak + */ +class MemcachedSessionStorage extends AbstractSessionStorage implements SessionSaveHandlerInterface +{ + /** + * Memcached driver. + * + * @var Memcached + */ + private $memcached; + + /** + * Configuration options. + * + * @var array + */ + private $memcachedOptions; + + /** + * Constructor. + * + * @param \Memcached $memcached A \Memcached instance + * @param array $memcachedOptions An associative array of Memcached options + * @param array $options Session configuration options. + * @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag) + * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag) + * + * @see AbstractSessionStorage::__construct() + */ + public function __construct(\Memcached $memcache, array $memcachedOptions = array(), array $options = array(), AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) + { + $this->memcached = $memcached; + + // defaults + if (!isset($memcachedOptions['serverpool'])) { + $memcachedOptions['serverpool'] = array( + 'host' => '127.0.0.1', + 'port' => 11211, + 'timeout' => 1, + 'persistent' => false, + 'weight' => 1); + } + + $memcachedOptions['expiretime'] = isset($memcachedOptions['expiretime']) ? (int)$memcachedOptions['expiretime'] : 86400; + + $this->memcached->setOption(\Memcached::OPT_PREFIX_KEY, isset($memcachedOptions['prefix']) ? $memcachedOption['prefix'] : 'sf2s'); + + $this->memcacheOptions = $memcachedOptions; + + parent::__construct($attributes, $flashes, $options); + } + + /** + * {@inheritdoc} + */ + public function sessionOpen($savePath, $sessionName) + { + foreach ($this->memcachedOptions['serverpool'] as $server) { + $this->addServer($server); + } + + return true; + } + + /** + * Close session. + * + * @return boolean + */ + public function sessionClose() + { + return $this->memcached->close(); + } + + /** + * {@inheritdoc} + */ + public function sessionRead($sessionId) + { + $result = $this->memcached->get($this->prefix.$sessionId); + + return $result ? $result : ''; + } + + /** + * {@inheritdoc} + */ + public function sessionWrite($sessionId, $data) + { + return $this->memcached->set($this->prefix.$sessionId, $data, false, $this->memcachedOptions['expiretime']); + } + + /** + * {@inheritdoc} + */ + public function sessionDestroy($sessionId) + { + return $this->memcached->delete($this->prefix.$sessionId); + } + + /** + * {@inheritdoc} + */ + public function sessionGc($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/SessionStorage/NullSessionStorage.php b/src/Symfony/Component/HttpFoundation/SessionStorage/NullSessionStorage.php new file mode 100644 index 0000000000..bb62c50bd4 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/SessionStorage/NullSessionStorage.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\SessionStorage; + +use Symfony\Component\HttpFoundation\AttributeBagInterface; +use Symfony\Component\HttpFoundation\FlashBagInterface; + +/** + * NullSessionStorage. + * + * Can be used in unit testing or in a sitation where persisted sessions are not desired. + * + * @author Drak + * + * @api + */ +class NullSessionStorage extends AbstractSessionStorage implements SessionSaveHandlerInterface +{ + /** + * {@inheritdoc} + */ + public function sessionOpen($savePath, $sessionName) + { + return true; + } + + /** + * Close session. + * + * @return boolean + */ + public function sessionClose() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function sessionRead($sessionId) + { + return ''; + } + + /** + * {@inheritdoc} + */ + public function sessionWrite($sessionId, $data) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function sessionDestroy($sessionId) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function sessionGc($lifetime) + { + return true; + } +} diff --git a/tests/Symfony/Tests/Component/HttpFoundation/SessionStorage/NullSessionStorageTest.php b/tests/Symfony/Tests/Component/HttpFoundation/SessionStorage/NullSessionStorageTest.php new file mode 100644 index 0000000000..a8fcf98c40 --- /dev/null +++ b/tests/Symfony/Tests/Component/HttpFoundation/SessionStorage/NullSessionStorageTest.php @@ -0,0 +1,52 @@ + + * + * @runTestsInSeparateProcesses + */ +class NullSessionStorageTest extends \PHPUnit_Framework_TestCase +{ + public function testConstructDefaults() + { + $storage = new NullSessionStorage(); + $this->assertEquals('user', ini_get('session.save_handler')); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\AttributeBagInterface', $storage->getAttributes()); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\FlashBagInterface', $storage->getFlashes()); + } + + public function testSaveHandlers() + { + $storage = new NullSessionStorage(); + $this->assertEquals('user', ini_get('session.save_handler')); + } + + public function testSession() + { + session_id('nullsessionstorage'); + $storage = new NullSessionStorage(); + $session = new Session($storage); + $this->assertNull($session->get('something')); + $session->set('something', 'unique'); + $this->assertEquals('unique', $session->get('something')); + } + + public function testNothingIsPersisted() + { + session_id('nullsessionstorage'); + $storage = new NullSessionStorage(); + $session = new Session($storage); + $session->start(); + $this->assertEquals('nullsessionstorage', $session->getId()); + $this->assertNull($session->get('something')); + } +} +