Updated Symfony HttpFoundation to 2.1.6.

This commit is contained in:
Taylor Otwell
2013-01-06 13:58:32 -06:00
parent f754e1fa55
commit cb567c5e4d
55 changed files with 1758 additions and 805 deletions

View File

@@ -14,7 +14,7 @@ namespace Symfony\Component\HttpFoundation\Session\Attribute;
/**
* This class relates to session attribute storage
*/
class AttributeBag implements AttributeBagInterface
class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable
{
private $name = 'attributes';
@@ -134,4 +134,24 @@ class AttributeBag implements AttributeBagInterface
return $return;
}
/**
* Returns an iterator for attributes.
*
* @return \ArrayIterator An \ArrayIterator instance
*/
public function getIterator()
{
return new \ArrayIterator($this->attributes);
}
/**
* Returns the number of attributes.
*
* @return int The number of attributes
*/
public function count()
{
return count($this->attributes);
}
}

View File

@@ -27,7 +27,7 @@ interface AttributeBagInterface extends SessionBagInterface
*
* @return Boolean true if the attribute is defined, false otherwise
*/
function has($name);
public function has($name);
/**
* Returns an attribute.
@@ -37,7 +37,7 @@ interface AttributeBagInterface extends SessionBagInterface
*
* @return mixed
*/
function get($name, $default = null);
public function get($name, $default = null);
/**
* Sets an attribute.
@@ -45,21 +45,21 @@ interface AttributeBagInterface extends SessionBagInterface
* @param string $name
* @param mixed $value
*/
function set($name, $value);
public function set($name, $value);
/**
* Returns attributes.
*
* @return array Attributes
*/
function all();
public function all();
/**
* Sets attributes.
*
* @param array $attributes Attributes
*/
function replace(array $attributes);
public function replace(array $attributes);
/**
* Removes an attribute.
@@ -68,5 +68,5 @@ interface AttributeBagInterface extends SessionBagInterface
*
* @return mixed The removed value
*/
function remove($name);
public function remove($name);
}

View File

@@ -75,7 +75,15 @@ class AutoExpireFlashBag implements FlashBagInterface
/**
* {@inheritdoc}
*/
public function peek($type, $default = null)
public function add($type, $message)
{
$this->flashes['new'][$type][] = $message;
}
/**
* {@inheritdoc}
*/
public function peek($type, array $default = array())
{
return $this->has($type) ? $this->flashes['display'][$type] : $default;
}
@@ -85,13 +93,13 @@ class AutoExpireFlashBag implements FlashBagInterface
*/
public function peekAll()
{
return array_key_exists('display', $this->flashes) ? (array)$this->flashes['display'] : array();
return array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : array();
}
/**
* {@inheritdoc}
*/
public function get($type, $default = null)
public function get($type, array $default = array())
{
$return = $default;
@@ -129,9 +137,9 @@ class AutoExpireFlashBag implements FlashBagInterface
/**
* {@inheritdoc}
*/
public function set($type, $message)
public function set($type, $messages)
{
$this->flashes['new'][$type] = $message;
$this->flashes['new'][$type] = (array) $messages;
}
/**
@@ -139,7 +147,7 @@ class AutoExpireFlashBag implements FlashBagInterface
*/
public function has($type)
{
return array_key_exists($type, $this->flashes['display']);
return array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type];
}
/**
@@ -163,9 +171,6 @@ class AutoExpireFlashBag implements FlashBagInterface
*/
public function clear()
{
$return = $this->all();
$this->flashes = array('display' => array(), 'new' => array());
return $return;
return $this->all();
}
}

View File

@@ -16,7 +16,7 @@ namespace Symfony\Component\HttpFoundation\Session\Flash;
*
* @author Drak <drak@zikula.org>
*/
class FlashBag implements FlashBagInterface
class FlashBag implements FlashBagInterface, \IteratorAggregate, \Countable
{
private $name = 'flashes';
@@ -68,7 +68,15 @@ class FlashBag implements FlashBagInterface
/**
* {@inheritdoc}
*/
public function peek($type, $default = null)
public function add($type, $message)
{
$this->flashes[$type][] = $message;
}
/**
* {@inheritdoc}
*/
public function peek($type, array $default =array())
{
return $this->has($type) ? $this->flashes[$type] : $default;
}
@@ -84,7 +92,7 @@ class FlashBag implements FlashBagInterface
/**
* {@inheritdoc}
*/
public function get($type, $default = null)
public function get($type, array $default = array())
{
if (!$this->has($type)) {
return $default;
@@ -111,9 +119,9 @@ class FlashBag implements FlashBagInterface
/**
* {@inheritdoc}
*/
public function set($type, $message)
public function set($type, $messages)
{
$this->flashes[$type] = $message;
$this->flashes[$type] = (array) $messages;
}
/**
@@ -129,7 +137,7 @@ class FlashBag implements FlashBagInterface
*/
public function has($type)
{
return array_key_exists($type, $this->flashes);
return array_key_exists($type, $this->flashes) && $this->flashes[$type];
}
/**
@@ -155,4 +163,24 @@ class FlashBag implements FlashBagInterface
{
return $this->all();
}
/**
* Returns an iterator for flashes.
*
* @return \ArrayIterator An \ArrayIterator instance
*/
public function getIterator()
{
return new \ArrayIterator($this->all());
}
/**
* Returns the number of flashes.
*
* @return int The number of flashes
*/
public function count()
{
return count($this->flashes);
}
}

View File

@@ -21,51 +21,59 @@ use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
interface FlashBagInterface extends SessionBagInterface
{
/**
* Registers a message for a given type.
* Adds a flash message for type.
*
* @param string $type
* @param string $message
*/
function set($type, $message);
public function add($type, $message);
/**
* Gets flash message for a given type.
* Registers a message for a given type.
*
* @param string $type
* @param string|array $message
*/
public function set($type, $message);
/**
* Gets flash messages for a given type.
*
* @param string $type Message category type.
* @param string $default Default value if $type doee not exist.
* @param array $default Default value if $type does not exist.
*
* @return string
* @return array
*/
function peek($type, $default = null);
public function peek($type, array $default = array());
/**
* Gets all flash messages.
*
* @return array
*/
function peekAll();
public function peekAll();
/**
* Gets and clears flash from the stack.
*
* @param string $type
* @param string $default Default value if $type doee not exist.
* @param array $default Default value if $type does not exist.
*
* @return string
* @return array
*/
function get($type, $default = null);
public function get($type, array $default = array());
/**
* Gets and clears flashes from the stack.
*
* @return array
*/
function all();
public function all();
/**
* Sets all flash messages.
*/
function setAll(array $messages);
public function setAll(array $messages);
/**
* Has flash messages for a given type?
@@ -74,12 +82,12 @@ interface FlashBagInterface extends SessionBagInterface
*
* @return boolean
*/
function has($type);
public function has($type);
/**
* Returns a list of all defined types.
*
* @return array
*/
function keys();
public function keys();
}

View File

@@ -27,7 +27,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
*
* @api
*/
class Session implements SessionInterface
class Session implements SessionInterface, \IteratorAggregate, \Countable
{
/**
* Storage driver.
@@ -57,13 +57,13 @@ class Session implements SessionInterface
{
$this->storage = $storage ?: new NativeSessionStorage();
$attributeBag = $attributes ?: new AttributeBag();
$this->attributeName = $attributeBag->getName();
$this->registerBag($attributeBag);
$attributes = $attributes ?: new AttributeBag();
$this->attributeName = $attributes->getName();
$this->registerBag($attributes);
$flashBag = $flashes ?: new FlashBag();
$this->flashName = $flashBag->getName();
$this->registerBag($flashBag);
$flashes = $flashes ?: new FlashBag();
$this->flashName = $flashes->getName();
$this->registerBag($flashes);
}
/**
@@ -133,19 +133,47 @@ class Session implements SessionInterface
/**
* {@inheritdoc}
*/
public function invalidate()
public function isStarted()
{
$this->storage->clear();
return $this->storage->isStarted();
}
return $this->storage->regenerate(true);
/**
* Returns an iterator for attributes.
*
* @return \ArrayIterator An \ArrayIterator instance
*/
public function getIterator()
{
return new \ArrayIterator($this->storage->getBag($this->attributeName)->all());
}
/**
* Returns the number of attributes.
*
* @return int The number of attributes
*/
public function count()
{
return count($this->storage->getBag($this->attributeName)->all());
}
/**
* {@inheritdoc}
*/
public function migrate($destroy = false)
public function invalidate($lifetime = null)
{
return $this->storage->regenerate($destroy);
$this->storage->clear();
return $this->migrate(true, $lifetime);
}
/**
* {@inheritdoc}
*/
public function migrate($destroy = false, $lifetime = null)
{
return $this->storage->regenerate($destroy, $lifetime);
}
/**
@@ -189,9 +217,15 @@ class Session implements SessionInterface
}
/**
* Registers a SessionBagInterface with the session.
*
* @param SessionBagInterface $bag
* {@inheritdoc}
*/
public function getMetadataBag()
{
return $this->storage->getMetadataBag();
}
/**
* {@inheritdoc}
*/
public function registerBag(SessionBagInterface $bag)
{
@@ -199,11 +233,7 @@ class Session implements SessionInterface
}
/**
* Get's a bag instance.
*
* @param string $name
*
* @return SessionBagInterface
* {@inheritdoc}
*/
public function getBag($name)
{
@@ -229,7 +259,20 @@ class Session implements SessionInterface
*/
public function getFlashes()
{
return $this->getBag('flashes')->all();
$all = $this->getBag($this->flashName)->all();
$return = array();
if ($all) {
foreach ($all as $name => $array) {
if (is_numeric(key($array))) {
$return[$name] = reset($array);
} else {
$return[$name] = $array;
}
}
}
return $return;
}
/**
@@ -239,7 +282,9 @@ class Session implements SessionInterface
*/
public function setFlashes($values)
{
$this->getBag('flashes')->setAll($values);
foreach ($values as $name => $value) {
$this->getBag($this->flashName)->set($name, $value);
}
}
/**
@@ -252,7 +297,9 @@ class Session implements SessionInterface
*/
public function getFlash($name, $default = null)
{
return $this->getBag('flashes')->get($name, $default);
$return = $this->getBag($this->flashName)->get($name);
return empty($return) ? $default : reset($return);
}
/**
@@ -263,7 +310,7 @@ class Session implements SessionInterface
*/
public function setFlash($name, $value)
{
$this->getBag('flashes')->set($name, $value);
$this->getBag($this->flashName)->set($name, $value);
}
/**
@@ -275,7 +322,7 @@ class Session implements SessionInterface
*/
public function hasFlash($name)
{
return $this->getBag('flashes')->has($name);
return $this->getBag($this->flashName)->has($name);
}
/**
@@ -285,7 +332,7 @@ class Session implements SessionInterface
*/
public function removeFlash($name)
{
$this->getBag('flashes')->get($name);
$this->getBag($this->flashName)->get($name);
}
/**
@@ -295,6 +342,6 @@ class Session implements SessionInterface
*/
public function clearFlashes()
{
return $this->getBag('flashes')->clear();
return $this->getBag($this->flashName)->clear();
}
}

View File

@@ -23,26 +23,26 @@ interface SessionBagInterface
*
* @return string
*/
function getName();
public function getName();
/**
* Initializes the Bag
*
* @param array $array
*/
function initialize(array &$array);
public function initialize(array &$array);
/**
* Gets the storage key for this bag.
*
* @return string
*/
function getStorageKey();
public function getStorageKey();
/**
* Clears out data from bag.
*
* @return mixed Whatever data was contained.
*/
function clear();
public function clear();
}

View File

@@ -11,6 +11,8 @@
namespace Symfony\Component\HttpFoundation\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
/**
* Interface for the session.
*
@@ -27,7 +29,7 @@ interface SessionInterface
*
* @api
*/
function start();
public function start();
/**
* Returns the session ID.
@@ -36,7 +38,7 @@ interface SessionInterface
*
* @api
*/
function getId();
public function getId();
/**
* Sets the session ID
@@ -45,7 +47,7 @@ interface SessionInterface
*
* @api
*/
function setId($id);
public function setId($id);
/**
* Returns the session name.
@@ -54,7 +56,7 @@ interface SessionInterface
*
* @api
*/
function getName();
public function getName();
/**
* Sets the session name.
@@ -63,7 +65,7 @@ interface SessionInterface
*
* @api
*/
function setName($name);
public function setName($name);
/**
* Invalidates the current session.
@@ -71,23 +73,32 @@ interface SessionInterface
* Clears all session attributes and flashes and regenerates the
* session and deletes the old session from persistence.
*
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
* @return Boolean True if session invalidated, false if error.
*
* @api
*/
function invalidate();
public function invalidate($lifetime = null);
/**
* Migrates the current session to a new session id while maintaining all
* session attributes.
*
* @param Boolean $destroy Whether to delete the old session or leave it to garbage collection.
* @param Boolean $destroy Whether to delete the old session or leave it to garbage collection.
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
* @return Boolean True if session migrated, false if error.
*
* @api
*/
function migrate($destroy = false);
public function migrate($destroy = false, $lifetime = null);
/**
* Force the session to be saved and closed.
@@ -96,7 +107,7 @@ interface SessionInterface
* the session will be automatically saved at the end of
* code execution.
*/
function save();
public function save();
/**
* Checks if an attribute is defined.
@@ -107,7 +118,7 @@ interface SessionInterface
*
* @api
*/
function has($name);
public function has($name);
/**
* Returns an attribute.
@@ -119,7 +130,7 @@ interface SessionInterface
*
* @api
*/
function get($name, $default = null);
public function get($name, $default = null);
/**
* Sets an attribute.
@@ -129,7 +140,7 @@ interface SessionInterface
*
* @api
*/
function set($name, $value);
public function set($name, $value);
/**
* Returns attributes.
@@ -138,14 +149,14 @@ interface SessionInterface
*
* @api
*/
function all();
public function all();
/**
* Sets attributes.
*
* @param array $attributes Attributes
*/
function replace(array $attributes);
public function replace(array $attributes);
/**
* Removes an attribute.
@@ -156,12 +167,42 @@ interface SessionInterface
*
* @api
*/
function remove($name);
public function remove($name);
/**
* Clears all attributes.
*
* @api
*/
function clear();
public function clear();
/**
* Checks if the session was started.
*
* @return Boolean
*/
public function isStarted();
/**
* Registers a SessionBagInterface with the session.
*
* @param SessionBagInterface $bag
*/
public function registerBag(SessionBagInterface $bag);
/**
* Gets a bag instance by name.
*
* @param string $name
*
* @return SessionBagInterface
*/
public function getBag($name);
/**
* Gets session meta.
*
* @return MetadataBag
*/
public function getMetadataBag();
}

View File

@@ -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,15 +83,15 @@ class MemcacheSessionHandler implements \SessionHandlerInterface
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function write($sessionId, $data)
{
return $this->memcache->set($this->prefix.$sessionId, $data, 0, $this->memcacheOptions['expiretime']);
return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl);
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function destroy($sessionId)
{
@@ -129,7 +99,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function gc($lifetime)
{

View File

@@ -24,55 +24,56 @@ 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 +81,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;
}
}

View File

@@ -0,0 +1,150 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
/**
* MongoDB session handler
*
* @author Markus Bachmann <markus.bachmann@bachi.biz>
*/
class MongoDbSessionHandler implements \SessionHandlerInterface
{
/**
* @var \Mongo
*/
private $mongo;
/**
* @var \MongoCollection
*/
private $collection;
/**
* @var array
*/
private $options;
/**
* Constructor.
*
* @param \Mongo|\MongoClient $mongo A MongoClient or Mongo instance
* @param array $options An associative array of field options
*
* @throws \InvalidArgumentException When MongoClient or Mongo instance not provided
* @throws \InvalidArgumentException When "database" or "collection" not provided
*/
public function __construct($mongo, array $options)
{
if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) {
throw new \InvalidArgumentException('MongoClient or Mongo instance required');
}
if (!isset($options['database']) || !isset($options['collection'])) {
throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler');
}
$this->mongo = $mongo;
$this->options = array_merge(array(
'id_field' => 'sess_id',
'data_field' => 'sess_data',
'time_field' => 'sess_time',
), $options);
}
/**
* {@inheritDoc}
*/
public function open($savePath, $sessionName)
{
return true;
}
/**
* {@inheritDoc}
*/
public function close()
{
return true;
}
/**
* {@inheritDoc}
*/
public function destroy($sessionId)
{
$this->getCollection()->remove(
array($this->options['id_field'] => $sessionId),
array('justOne' => true)
);
return true;
}
/**
* {@inheritDoc}
*/
public function gc($lifetime)
{
$time = new \MongoTimestamp(time() - $lifetime);
$this->getCollection()->remove(array(
$this->options['time_field'] => array('$lt' => $time),
));
}
/**
* {@inheritDoc]
*/
public function write($sessionId, $data)
{
$data = array(
$this->options['id_field'] => $sessionId,
$this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY),
$this->options['time_field'] => new \MongoTimestamp()
);
$this->getCollection()->update(
array($this->options['id_field'] => $sessionId),
array('$set' => $data),
array('upsert' => true)
);
return true;
}
/**
* {@inheritDoc}
*/
public function read($sessionId)
{
$dbData = $this->getCollection()->findOne(array(
$this->options['id_field'] => $sessionId,
));
return null === $dbData ? '' : $dbData[$this->options['data_field']]->bin;
}
/**
* Return a "MongoCollection" instance
*
* @return \MongoCollection
*/
private function getCollection()
{
if (null === $this->collection) {
$this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']);
}
return $this->collection;
}
}

View File

@@ -23,7 +23,13 @@ class NativeFileSessionHandler extends NativeSessionHandler
/**
* Constructor.
*
* @param string $savePath Path of directory to save session files. Default null will leave setting as defined by PHP.
* @param string $savePath Path of directory to save session files.
* Default null will leave setting as defined by PHP.
* '/path', 'N;/path', or 'N;octal-mode;/path
*
* @see http://php.net/session.configuration.php#ini.session.save-path for further details.
*
* @throws \InvalidArgumentException On invalid $savePath
*/
public function __construct($savePath = null)
{
@@ -31,11 +37,22 @@ class NativeFileSessionHandler extends NativeSessionHandler
$savePath = ini_get('session.save_path');
}
if ($savePath && !is_dir($savePath)) {
mkdir($savePath, 0777, true);
$baseDir = $savePath;
if ($count = substr_count($savePath, ';')) {
if ($count > 2) {
throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath));
}
// characters after last ';' are the path
$baseDir = ltrim(strrchr($savePath, ';'), ';');
}
if ($baseDir && !is_dir($baseDir)) {
mkdir($baseDir, 0777, true);
}
ini_set('session.save_handler', 'files');
ini_set('session.save_path', $savePath);
ini_set('session.save_handler', 'files');
}
}

View File

@@ -1,65 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
/**
* NativeMemcacheSessionHandler.
*
* Driver for the memcache session save hadlers provided by the memcache PHP extension.
*
* @see http://php.net/memcache
*
* @author Drak <drak@zikula.org>
*/
class NativeMemcacheSessionHandler extends NativeSessionHandler
{
/**
* Constructor.
*
* @param string $savePath Path of memcache server.
* @param array $options Session configuration options.
*/
public function __construct($savePath = 'tcp://127.0.0.1:11211?persistent=0', array $options = array())
{
if (!extension_loaded('memcache')) {
throw new \RuntimeException('PHP does not have "memcache" session module registered');
}
if (null === $savePath) {
$savePath = ini_get('session.save_path');
}
ini_set('session.save_handler', 'memcache');
ini_set('session.save_path', $savePath);
$this->setOptions($options);
}
/**
* Set any memcached ini values.
*
* @see http://php.net/memcache.ini
*/
protected function setOptions(array $options)
{
foreach ($options as $key => $value) {
if (in_array($key, array(
'memcache.allow_failover', 'memcache.max_failover_attempts',
'memcache.chunk_size', 'memcache.default_port', 'memcache.hash_strategy',
'memcache.hash_function', 'memcache.protocol', 'memcache.redundancy',
'memcache.session_redundancy', 'memcache.compress_threshold',
'memcache.lock_timeout'))) {
ini_set($key, $value);
}
}
}
}

View File

@@ -1,64 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
/**
* NativeMemcachedSessionHandler.
*
* Driver for the memcached session save hadlers provided by the memcached PHP extension.
*
* @see http://php.net/memcached.sessions
*
* @author Drak <drak@zikula.org>
*/
class NativeMemcachedSessionHandler extends NativeSessionHandler
{
/**
* Constructor.
*
* @param string $savePath Comma separated list of servers: e.g. memcache1.example.com:11211,memcache2.example.com:11211
* @param array $options Session configuration options.
*/
public function __construct($savePath = '127.0.0.1:11211', array $options = array())
{
if (!extension_loaded('memcached')) {
throw new \RuntimeException('PHP does not have "memcached" session module registered');
}
if (null === $savePath) {
$savePath = ini_get('session.save_path');
}
ini_set('session.save_handler', 'memcached');
ini_set('session.save_path', $savePath);
$this->setOptions($options);
}
/**
* Set any memcached ini values.
*
* @see https://github.com/php-memcached-dev/php-memcached/blob/master/memcached.ini
*/
protected function setOptions(array $options)
{
foreach ($options as $key => $value) {
if (in_array($key, array(
'memcached.sess_locking', 'memcached.sess_lock_wait',
'memcached.sess_prefix', 'memcached.compression_type',
'memcached.compression_factor', 'memcached.compression_threshold',
'memcached.serializer'))) {
ini_set($key, $value);
}
}
}
}

View File

@@ -1,58 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
/**
* NativeSqliteSessionHandler.
*
* Driver for the sqlite session save hadlers provided by the SQLite PHP extension.
*
* @author Drak <drak@zikula.org>
*/
class NativeSqliteSessionHandler extends NativeSessionHandler
{
/**
* Constructor.
*
* @param string $savePath Path to SQLite database file itself.
* @param array $options Session configuration options.
*/
public function __construct($savePath, array $options = array())
{
if (!extension_loaded('sqlite')) {
throw new \RuntimeException('PHP does not have "sqlite" session module registered');
}
if (null === $savePath) {
$savePath = ini_get('session.save_path');
}
ini_set('session.save_handler', 'sqlite');
ini_set('session.save_path', $savePath);
$this->setOptions($options);
}
/**
* Set any sqlite ini values.
*
* @see http://php.net/sqlite.configuration
*/
protected function setOptions(array $options)
{
foreach ($options as $key => $value) {
if (in_array($key, array('sqlite.assoc_case'))) {
ini_set($key, $value);
}
}
}
}

View File

@@ -14,7 +14,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
/**
* NullSessionHandler.
*
* Can be used in unit testing or in a sitation where persisted sessions are not desired.
* Can be used in unit testing or in a situations where persisted sessions are not desired.
*
* @author Drak <drak@zikula.org>
*

View File

@@ -20,30 +20,30 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
class PdoSessionHandler implements \SessionHandlerInterface
{
/**
* PDO instance.
*
* @var \PDO
* @var \PDO PDO instance.
*/
private $pdo;
/**
* Database options.
*
*
* @var array
* @var array Database options.
*/
private $dbOptions;
/**
* Constructor.
*
* List of available options:
* * db_table: The name of the table [required]
* * db_id_col: The column where to store the session id [default: sess_id]
* * db_data_col: The column where to store the session data [default: sess_data]
* * db_time_col: The column where to store the timestamp [default: sess_time]
*
* @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 +58,7 @@ class PdoSessionHandler implements \SessionHandlerInterface
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function open($path, $name)
{
@@ -66,7 +66,7 @@ class PdoSessionHandler implements \SessionHandlerInterface
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function close()
{
@@ -74,12 +74,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 +97,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 +120,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 +154,7 @@ class PdoSessionHandler implements \SessionHandlerInterface
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function write($id, $data)
{
@@ -164,27 +164,47 @@ class PdoSessionHandler implements \SessionHandlerInterface
$dbIdCol = $this->dbOptions['db_id_col'];
$dbTimeCol = $this->dbOptions['db_time_col'];
$sql = ('mysql' === $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME))
? "INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time) "
."ON DUPLICATE KEY UPDATE $dbDataCol = VALUES($dbDataCol), $dbTimeCol = CASE WHEN $dbTimeCol = :time THEN (VALUES($dbTimeCol) + 1) ELSE VALUES($dbTimeCol) END"
: "UPDATE $dbTable SET $dbDataCol = :data, $dbTimeCol = :time WHERE $dbIdCol = :id";
//session data can contain non binary safe characters so we need to encode it
$encoded = base64_encode($data);
try {
//session data can contain non binary safe characters so we need to encode it
$encoded = base64_encode($data);
$stmt = $this->pdo->prepare($sql);
$stmt->bindParam(':id', $id, \PDO::PARAM_STR);
$stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);
$stmt->execute();
$driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
if (!$stmt->rowCount()) {
// No session exists in the database to update. This happens when we have called
// session_regenerate_id()
$this->createNewSession($id, $data);
if ('mysql' === $driver) {
// MySQL would report $stmt->rowCount() = 0 on UPDATE when the data is left unchanged
// it could result in calling createNewSession() whereas the session already exists in
// the DB which would fail as the id is unique
$stmt = $this->pdo->prepare(
"INSERT INTO $dbTable ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, :time) " .
"ON DUPLICATE KEY UPDATE $dbDataCol = VALUES($dbDataCol), $dbTimeCol = VALUES($dbTimeCol)"
);
$stmt->bindParam(':id', $id, \PDO::PARAM_STR);
$stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);
$stmt->execute();
} elseif ('oci' === $driver) {
$stmt = $this->pdo->prepare("MERGE INTO $dbTable USING DUAL ON($dbIdCol = :id) ".
"WHEN NOT MATCHED THEN INSERT ($dbIdCol, $dbDataCol, $dbTimeCol) VALUES (:id, :data, sysdate) " .
"WHEN MATCHED THEN UPDATE SET $dbDataCol = :data WHERE $dbIdCol = :id");
$stmt->bindParam(':id', $id, \PDO::PARAM_STR);
$stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
$stmt->execute();
} else {
$stmt = $this->pdo->prepare("UPDATE $dbTable SET $dbDataCol = :data, $dbTimeCol = :time WHERE $dbIdCol = :id");
$stmt->bindParam(':id', $id, \PDO::PARAM_STR);
$stmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);
$stmt->execute();
if (!$stmt->rowCount()) {
// No session exists in the database to update. This happens when we have called
// session_regenerate_id()
$this->createNewSession($id, $data);
}
}
} catch (\PDOException $e) {
throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e);
throw new \RuntimeException(sprintf('PDOException was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e);
}
return true;
@@ -201,7 +221,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'];

View File

@@ -0,0 +1,160 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
/**
* Metadata container.
*
* Adds metadata to the session.
*
* @author Drak <drak@zikula.org>
*/
class MetadataBag implements SessionBagInterface
{
const CREATED = 'c';
const UPDATED = 'u';
const LIFETIME = 'l';
/**
* @var string
*/
private $name = '__metadata';
/**
* @var string
*/
private $storageKey;
/**
* @var array
*/
protected $meta = array();
/**
* Unix timestamp.
*
* @var integer
*/
private $lastUsed;
/**
* Constructor.
*
* @param string $storageKey The key used to store bag in the session.
*/
public function __construct($storageKey = '_sf2_meta')
{
$this->storageKey = $storageKey;
$this->meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0);
}
/**
* {@inheritdoc}
*/
public function initialize(array &$array)
{
$this->meta = &$array;
if (isset($array[self::CREATED])) {
$this->lastUsed = $this->meta[self::UPDATED];
$this->meta[self::UPDATED] = time();
} else {
$this->stampCreated();
}
}
/**
* Gets the lifetime that the session cookie was set with.
*
* @return integer
*/
public function getLifetime()
{
return $this->meta[self::LIFETIME];
}
/**
* Stamps a new session's metadata.
*
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*/
public function stampNew($lifetime = null)
{
$this->stampCreated($lifetime);
}
/**
* {@inheritdoc}
*/
public function getStorageKey()
{
return $this->storageKey;
}
/**
* Gets the created timestamp metadata.
*
* @return integer Unix timestamp
*/
public function getCreated()
{
return $this->meta[self::CREATED];
}
/**
* Gets the last used metadata.
*
* @return integer Unix timestamp
*/
public function getLastUsed()
{
return $this->lastUsed;
}
/**
* {@inheritdoc}
*/
public function clear()
{
// nothing to do
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
/**
* Sets name.
*
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
private function stampCreated($lifetime = null)
{
$timeStamp = time();
$this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp;
$this->meta[self::LIFETIME] = (null === $lifetime) ? ini_get('session.cookie_lifetime') : $lifetime;
}
}

View File

@@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
/**
* MockArraySessionStorage mocks the session for unit tests.
@@ -52,14 +53,26 @@ class MockArraySessionStorage implements SessionStorageInterface
*/
protected $data = array();
/**
* @var MetadataBag
*/
protected $metadataBag;
/**
* @var array
*/
protected $bags;
/**
* Constructor.
*
* @param string $name Session name
* @param string $name Session name
* @param MetadataBag $metaBag MetadataBag instance.
*/
public function __construct($name = 'MOCKSESSID')
public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null)
{
$this->name = $name;
$this->setMetadataBag($metaBag);
}
/**
@@ -90,16 +103,16 @@ class MockArraySessionStorage implements SessionStorageInterface
return true;
}
/**
* {@inheritdoc}
*/
public function regenerate($destroy = false)
public function regenerate($destroy = false, $lifetime = null)
{
if (!$this->started) {
$this->start();
}
$this->metadataBag->stampNew($lifetime);
$this->id = $this->generateId();
return true;
@@ -146,6 +159,9 @@ class MockArraySessionStorage implements SessionStorageInterface
*/
public function save()
{
if (!$this->started || $this->closed) {
throw new \RuntimeException("Trying to save a session that was not started yet or was already closed");
}
// nothing to do since we don't persist the session data
$this->closed = false;
}
@@ -191,6 +207,38 @@ class MockArraySessionStorage implements SessionStorageInterface
return $this->bags[$name];
}
/**
* {@inheritdoc}
*/
public function isStarted()
{
return $this->started;
}
/**
* Sets the MetadataBag.
*
* @param MetadataBag $bag
*/
public function setMetadataBag(MetadataBag $bag = null)
{
if (null === $bag) {
$bag = new MetadataBag();
}
$this->metadataBag = $bag;
}
/**
* Gets the MetadataBag.
*
* @return MetadataBag
*/
public function getMetadataBag()
{
return $this->metadataBag;
}
/**
* Generates a session ID.
*
@@ -206,7 +254,9 @@ class MockArraySessionStorage implements SessionStorageInterface
protected function loadSession()
{
foreach ($this->bags as $bag) {
$bags = array_merge($this->bags, array($this->metadataBag));
foreach ($bags as $bag) {
$key = $bag->getStorageKey();
$this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array();
$bag->initialize($this->data[$key]);

View File

@@ -29,13 +29,19 @@ class MockFileSessionStorage extends MockArraySessionStorage
*/
private $savePath;
/**
* @var array
*/
private $sessionData;
/**
* Constructor.
*
* @param string $savePath Path of directory to save session files.
* @param string $name Session name.
* @param string $savePath Path of directory to save session files.
* @param string $name Session name.
* @param MetadataBag $metaBag MetadataBag instance.
*/
public function __construct($savePath = null, $name = 'MOCKSESSID')
public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null)
{
if (null === $savePath) {
$savePath = sys_get_temp_dir();
@@ -47,7 +53,7 @@ class MockFileSessionStorage extends MockArraySessionStorage
$this->savePath = $savePath;
parent::__construct($name);
parent::__construct($name, $metaBag);
}
/**
@@ -73,15 +79,17 @@ class MockFileSessionStorage extends MockArraySessionStorage
/**
* {@inheritdoc}
*/
public function regenerate($destroy = false)
public function regenerate($destroy = false, $lifetime = null)
{
if (!$this->started) {
$this->start();
}
if ($destroy) {
$this->destroy();
}
$this->id = $this->generateId();
return true;
return parent::regenerate($destroy, $lifetime);
}
/**
@@ -89,7 +97,16 @@ class MockFileSessionStorage extends MockArraySessionStorage
*/
public function save()
{
if (!$this->started) {
throw new \RuntimeException("Trying to save a session that was not started yet or was already closed");
}
file_put_contents($this->getFilePath(), serialize($this->data));
// this is needed for Silex, where the session object is re-used across requests
// in functional tests. In Symfony, the container is rebooted, so we don't have
// this issue
$this->started = false;
}
/**

View File

@@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
@@ -45,17 +46,24 @@ class NativeSessionStorage implements SessionStorageInterface
*/
protected $saveHandler;
/**
* @var MetadataBag
*/
protected $metadataBag;
/**
* Constructor.
*
* Depending on how you want the storage driver to behave you probably
* want top override this constructor entirely.
* want to override this constructor entirely.
*
* List of options for $options array with their defaults.
* @see http://php.net/session.configuration for options
* but we omit 'session.' from the beginning of the keys for convenience.
*
* auto_start, "0"
* ("auto_start", is not supported as it tells PHP to start a session before
* PHP starts to execute user-land code. Setting during runtime has no effect).
*
* cache_limiter, "nocache" (use "0" to prevent headers from being sent entirely).
* cookie_domain, ""
* cookie_httponly, ""
@@ -83,13 +91,12 @@ class NativeSessionStorage implements SessionStorageInterface
* upload_progress.min-freq, "1"
* url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
*
* @param array $options Session configuration options.
* @param object $handler SessionHandlerInterface.
* @param array $options Session configuration options.
* @param object $handler SessionHandlerInterface.
* @param MetadataBag $metaBag MetadataBag.
*/
public function __construct(array $options = array(), $handler = null)
public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
{
// sensible defaults
ini_set('session.auto_start', 0); // by default we prefer to explicitly start the session using the class.
ini_set('session.cache_limiter', ''); // disable by default because it's managed by HeaderBag (if used)
ini_set('session.use_cookies', 1);
@@ -99,6 +106,7 @@ class NativeSessionStorage implements SessionStorageInterface
register_shutdown_function('session_write_close');
}
$this->setMetadataBag($metaBag);
$this->setOptions($options);
$this->setSaveHandler($handler);
}
@@ -165,7 +173,7 @@ class NativeSessionStorage implements SessionStorageInterface
*/
public function setId($id)
{
return $this->saveHandler->setId($id);
$this->saveHandler->setId($id);
}
/**
@@ -187,8 +195,16 @@ class NativeSessionStorage implements SessionStorageInterface
/**
* {@inheritdoc}
*/
public function regenerate($destroy = false)
public function regenerate($destroy = false, $lifetime = null)
{
if (null !== $lifetime) {
ini_set('session.cookie_lifetime', $lifetime);
}
if ($destroy) {
$this->metadataBag->stampNew();
}
return session_regenerate_id($destroy);
}
@@ -240,15 +256,47 @@ class NativeSessionStorage implements SessionStorageInterface
throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
}
if (ini_get('session.auto_start') && !$this->started) {
$this->start();
} elseif ($this->saveHandler->isActive() && !$this->started) {
if ($this->saveHandler->isActive() && !$this->started) {
$this->loadSession();
} elseif (!$this->started) {
$this->start();
}
return $this->bags[$name];
}
/**
* Sets the MetadataBag.
*
* @param MetadataBag $metaBag
*/
public function setMetadataBag(MetadataBag $metaBag = null)
{
if (null === $metaBag) {
$metaBag = new MetadataBag();
}
$this->metadataBag = $metaBag;
}
/**
* Gets the MetadataBag.
*
* @return MetadataBag
*/
public function getMetadataBag()
{
return $this->metadataBag;
}
/**
* {@inheritdoc}
*/
public function isStarted()
{
return $this->started;
}
/**
* Sets session.* ini variables.
*
@@ -261,17 +309,20 @@ class NativeSessionStorage implements SessionStorageInterface
*/
public function setOptions(array $options)
{
$validOptions = array_flip(array(
'cache_limiter', 'cookie_domain', 'cookie_httponly',
'cookie_lifetime', 'cookie_path', 'cookie_secure',
'entropy_file', 'entropy_length', 'gc_divisor',
'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
'hash_function', 'name', 'referer_check',
'serialize_handler', 'use_cookies',
'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags',
));
foreach ($options as $key => $value) {
if (in_array($key, array(
'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly',
'cookie_lifetime', 'cookie_path', 'cookie_secure',
'entropy_file', 'entropy_length', 'gc_divisor',
'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character',
'hash_function', 'name', 'referer_check',
'serialize_handler', 'use_cookies',
'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags'))) {
if (isset($validOptions[$key])) {
ini_set('session.'.$key, $value);
}
}
@@ -298,7 +349,7 @@ class NativeSessionStorage implements SessionStorageInterface
if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
$saveHandler = new SessionHandlerProxy($saveHandler);
} elseif (!$saveHandler instanceof AbstractProxy) {
$saveHandler = new NativeProxy($saveHandler);
$saveHandler = new NativeProxy();
}
$this->saveHandler = $saveHandler;
@@ -335,7 +386,9 @@ class NativeSessionStorage implements SessionStorageInterface
$session = &$_SESSION;
}
foreach ($this->bags as $bag) {
$bags = array_merge($this->bags, array($this->metadataBag));
foreach ($bags as $bag) {
$key = $bag->getStorageKey();
$session[$key] = isset($session[$key]) ? $session[$key] : array();
$bag->initialize($session[$key]);

View File

@@ -58,7 +58,7 @@ abstract class AbstractProxy
/**
* Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
*
* @return bool
* @return Boolean
*/
public function isWrapper()
{
@@ -68,7 +68,7 @@ abstract class AbstractProxy
/**
* Has a session started?
*
* @return bool
* @return Boolean
*/
public function isActive()
{
@@ -78,7 +78,7 @@ abstract class AbstractProxy
/**
* Sets the active flag.
*
* @param bool $flag
* @param Boolean $flag
*/
public function setActive($flag)
{

View File

@@ -32,7 +32,7 @@ class NativeProxy extends AbstractProxy
/**
* Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
*
* @return bool False.
* @return Boolean False.
*/
public function isWrapper()
{

View File

@@ -42,7 +42,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
*/
public function open($savePath, $sessionName)
{
$return = (bool)$this->handler->open($savePath, $sessionName);
$return = (bool) $this->handler->open($savePath, $sessionName);
if (true === $return) {
$this->active = true;

View File

@@ -12,6 +12,7 @@
namespace Symfony\Component\HttpFoundation\Session\Storage;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
/**
* StorageInterface.
@@ -32,7 +33,14 @@ interface SessionStorageInterface
*
* @api
*/
function start();
public function start();
/**
* Checks if the session is started.
*
* @return boolean True if started, false otherwise.
*/
public function isStarted();
/**
* Returns the session ID
@@ -41,7 +49,7 @@ interface SessionStorageInterface
*
* @api
*/
function getId();
public function getId();
/**
* Sets the session ID
@@ -50,7 +58,7 @@ interface SessionStorageInterface
*
* @api
*/
function setId($id);
public function setId($id);
/**
* Returns the session name
@@ -59,7 +67,7 @@ interface SessionStorageInterface
*
* @api
*/
function getName();
public function getName();
/**
* Sets the session name
@@ -68,7 +76,7 @@ interface SessionStorageInterface
*
* @api
*/
function setName($name);
public function setName($name);
/**
* Regenerates id that represents this storage.
@@ -81,7 +89,11 @@ interface SessionStorageInterface
* Note regenerate+destroy should not clear the session data in memory
* only delete the session data from persistent storage.
*
* @param Boolean $destroy Destroy session when regenerating?
* @param Boolean $destroy Destroy session when regenerating?
* @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
* @return Boolean True if session regenerated, false if error
*
@@ -89,7 +101,7 @@ interface SessionStorageInterface
*
* @api
*/
function regenerate($destroy = false);
public function regenerate($destroy = false, $lifetime = null);
/**
* Force the session to be saved and closed.
@@ -98,13 +110,16 @@ interface SessionStorageInterface
* used for a storage object design for unit or functional testing where
* a real PHP session would interfere with testing, in which case it
* it should actually persist the session data if required.
*
* @throws \RuntimeException If the session is saved without being started, or if the session
* is already closed.
*/
function save();
public function save();
/**
* Clear all session data in memory.
*/
function clear();
public function clear();
/**
* Gets a SessionBagInterface by name.
@@ -115,12 +130,17 @@ interface SessionStorageInterface
*
* @throws \InvalidArgumentException If the bag does not exist
*/
function getBag($name);
public function getBag($name);
/**
* Registers a SessionBagInterface for use.
*
* @param SessionBagInterface $bag
*/
function registerBag(SessionBagInterface $bag);
public function registerBag(SessionBagInterface $bag);
/**
* @return MetadataBag
*/
public function getMetadataBag();
}