Update to Drupal 8.2.6. For more information, see https://www.drupal.org/project/drupal/releases/8.2.6
This commit is contained in:
parent
db56c09587
commit
f1e72395cb
588 changed files with 26857 additions and 2777 deletions
|
@ -29,8 +29,8 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $storageKey Session storage key.
|
||||
* @param string $namespaceCharacter Namespace character to use in keys.
|
||||
* @param string $storageKey Session storage key
|
||||
* @param string $namespaceCharacter Namespace character to use in keys
|
||||
*/
|
||||
public function __construct($storageKey = '_sf2_attributes', $namespaceCharacter = '/')
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ class AutoExpireFlashBag implements FlashBagInterface
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $storageKey The key used to store flashes in the session.
|
||||
* @param string $storageKey The key used to store flashes in the session
|
||||
*/
|
||||
public function __construct($storageKey = '_sf2_flashes')
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ class FlashBag implements FlashBagInterface, \IteratorAggregate
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $storageKey The key used to store flashes in the session.
|
||||
* @param string $storageKey The key used to store flashes in the session
|
||||
*/
|
||||
public function __construct($storageKey = '_sf2_flashes')
|
||||
{
|
||||
|
|
|
@ -39,8 +39,8 @@ interface FlashBagInterface extends SessionBagInterface
|
|||
/**
|
||||
* Gets flash messages for a given type.
|
||||
*
|
||||
* @param string $type Message category type.
|
||||
* @param array $default Default value if $type does not exist.
|
||||
* @param string $type Message category type
|
||||
* @param array $default Default value if $type does not exist
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -57,7 +57,7 @@ interface FlashBagInterface extends SessionBagInterface
|
|||
* Gets and clears flash from the stack.
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $default Default value if $type does not exist.
|
||||
* @param array $default Default value if $type does not exist
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -72,6 +72,8 @@ interface FlashBagInterface extends SessionBagInterface
|
|||
|
||||
/**
|
||||
* Sets all flash messages.
|
||||
*
|
||||
* @param array $messages
|
||||
*/
|
||||
public function setAll(array $messages);
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param SessionStorageInterface $storage A SessionStorageInterface instance.
|
||||
* @param SessionStorageInterface $storage A SessionStorageInterface instance
|
||||
* @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag)
|
||||
* @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag)
|
||||
*/
|
||||
|
|
|
@ -42,7 +42,7 @@ interface SessionBagInterface
|
|||
/**
|
||||
* Clears out data from bag.
|
||||
*
|
||||
* @return mixed Whatever data was contained.
|
||||
* @return mixed Whatever data was contained
|
||||
*/
|
||||
public function clear();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ interface SessionInterface
|
|||
/**
|
||||
* Starts the session storage.
|
||||
*
|
||||
* @return bool True if session started.
|
||||
* @return bool True if session started
|
||||
*
|
||||
* @throws \RuntimeException If session fails to start.
|
||||
*/
|
||||
|
@ -32,7 +32,7 @@ interface SessionInterface
|
|||
/**
|
||||
* Returns the session ID.
|
||||
*
|
||||
* @return string The session ID.
|
||||
* @return string The session ID
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
|
@ -46,7 +46,7 @@ interface SessionInterface
|
|||
/**
|
||||
* Returns the session name.
|
||||
*
|
||||
* @return mixed The session name.
|
||||
* @return mixed The session name
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
|
@ -68,7 +68,7 @@ interface SessionInterface
|
|||
* to expire with browser session. Time is in seconds, and is
|
||||
* not a Unix timestamp.
|
||||
*
|
||||
* @return bool True if session invalidated, false if error.
|
||||
* @return bool True if session invalidated, false if error
|
||||
*/
|
||||
public function invalidate($lifetime = null);
|
||||
|
||||
|
@ -76,13 +76,13 @@ interface SessionInterface
|
|||
* Migrates the current session to a new session id while maintaining all
|
||||
* session attributes.
|
||||
*
|
||||
* @param bool $destroy Whether to delete the old session or leave it to garbage collection.
|
||||
* @param bool $destroy Whether to delete the old session or leave it to garbage collection
|
||||
* @param int $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 bool True if session migrated, false if error.
|
||||
* @return bool True if session migrated, false if error
|
||||
*/
|
||||
public function migrate($destroy = false, $lifetime = null);
|
||||
|
||||
|
@ -108,7 +108,7 @@ interface SessionInterface
|
|||
* Returns an attribute.
|
||||
*
|
||||
* @param string $name The attribute name
|
||||
* @param mixed $default The default value if not found.
|
||||
* @param mixed $default The default value if not found
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
class MemcacheSessionHandler implements \SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var \Memcache Memcache driver.
|
||||
* @var \Memcache Memcache driver
|
||||
*/
|
||||
private $memcache;
|
||||
|
||||
|
@ -29,7 +29,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface
|
|||
private $ttl;
|
||||
|
||||
/**
|
||||
* @var string Key prefix for shared environments.
|
||||
* @var string Key prefix for shared environments
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
|
@ -71,7 +71,7 @@ class MemcacheSessionHandler implements \SessionHandlerInterface
|
|||
*/
|
||||
public function close()
|
||||
{
|
||||
return $this->memcache->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
class MemcachedSessionHandler implements \SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var \Memcached Memcached driver.
|
||||
* @var \Memcached Memcached driver
|
||||
*/
|
||||
private $memcached;
|
||||
|
||||
|
@ -34,7 +34,7 @@ class MemcachedSessionHandler implements \SessionHandlerInterface
|
|||
private $ttl;
|
||||
|
||||
/**
|
||||
* @var string Key prefix for shared environments.
|
||||
* @var string Key prefix for shared environments
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
class MongoDbSessionHandler implements \SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var \Mongo
|
||||
* @var \Mongo|\MongoClient|\MongoDB\Client
|
||||
*/
|
||||
private $mongo;
|
||||
|
||||
|
@ -61,15 +61,15 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||
* If you use such an index, you can drop `gc_probability` to 0 since
|
||||
* no garbage-collection is required.
|
||||
*
|
||||
* @param \Mongo|\MongoClient $mongo A MongoClient or Mongo instance
|
||||
* @param array $options An associative array of field options
|
||||
* @param \Mongo|\MongoClient|\MongoDB\Client $mongo A MongoDB\Client, 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)) {
|
||||
if (!($mongo instanceof \MongoDB\Client || $mongo instanceof \MongoClient || $mongo instanceof \Mongo)) {
|
||||
throw new \InvalidArgumentException('MongoClient or Mongo instance required');
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,9 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||
*/
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
$this->getCollection()->remove(array(
|
||||
$methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove';
|
||||
|
||||
$this->getCollection()->$methodName(array(
|
||||
$this->options['id_field'] => $sessionId,
|
||||
));
|
||||
|
||||
|
@ -120,8 +122,10 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
$this->getCollection()->remove(array(
|
||||
$this->options['expiry_field'] => array('$lt' => new \MongoDate()),
|
||||
$methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove';
|
||||
|
||||
$this->getCollection()->$methodName(array(
|
||||
$this->options['expiry_field'] => array('$lt' => $this->createDateTime()),
|
||||
));
|
||||
|
||||
return true;
|
||||
|
@ -132,18 +136,28 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||
*/
|
||||
public function write($sessionId, $data)
|
||||
{
|
||||
$expiry = new \MongoDate(time() + (int) ini_get('session.gc_maxlifetime'));
|
||||
$expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime'));
|
||||
|
||||
$fields = array(
|
||||
$this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY),
|
||||
$this->options['time_field'] => new \MongoDate(),
|
||||
$this->options['time_field'] => $this->createDateTime(),
|
||||
$this->options['expiry_field'] => $expiry,
|
||||
);
|
||||
|
||||
$this->getCollection()->update(
|
||||
$options = array('upsert' => true);
|
||||
|
||||
if ($this->mongo instanceof \MongoDB\Client) {
|
||||
$fields[$this->options['data_field']] = new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY);
|
||||
} else {
|
||||
$fields[$this->options['data_field']] = new \MongoBinData($data, \MongoBinData::BYTE_ARRAY);
|
||||
$options['multiple'] = false;
|
||||
}
|
||||
|
||||
$methodName = $this->mongo instanceof \MongoDB\Client ? 'updateOne' : 'update';
|
||||
|
||||
$this->getCollection()->$methodName(
|
||||
array($this->options['id_field'] => $sessionId),
|
||||
array('$set' => $fields),
|
||||
array('upsert' => true, 'multiple' => false)
|
||||
$options
|
||||
);
|
||||
|
||||
return true;
|
||||
|
@ -156,10 +170,18 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||
{
|
||||
$dbData = $this->getCollection()->findOne(array(
|
||||
$this->options['id_field'] => $sessionId,
|
||||
$this->options['expiry_field'] => array('$gte' => new \MongoDate()),
|
||||
$this->options['expiry_field'] => array('$gte' => $this->createDateTime()),
|
||||
));
|
||||
|
||||
return null === $dbData ? '' : $dbData[$this->options['data_field']]->bin;
|
||||
if (null === $dbData) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($dbData[$this->options['data_field']] instanceof \MongoDB\BSON\Binary) {
|
||||
return $dbData[$this->options['data_field']]->getData();
|
||||
}
|
||||
|
||||
return $dbData[$this->options['data_field']]->bin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,10 +201,32 @@ class MongoDbSessionHandler implements \SessionHandlerInterface
|
|||
/**
|
||||
* Return a Mongo instance.
|
||||
*
|
||||
* @return \Mongo
|
||||
* @return \Mongo|\MongoClient|\MongoDB\Client
|
||||
*/
|
||||
protected function getMongo()
|
||||
{
|
||||
return $this->mongo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a date object using the class appropriate for the current mongo connection.
|
||||
*
|
||||
* Return an instance of a MongoDate or \MongoDB\BSON\UTCDateTime
|
||||
*
|
||||
* @param int $seconds An integer representing UTC seconds since Jan 1 1970. Defaults to now.
|
||||
*
|
||||
* @return \MongoDate|\MongoDB\BSON\UTCDateTime
|
||||
*/
|
||||
private function createDateTime($seconds = null)
|
||||
{
|
||||
if (null === $seconds) {
|
||||
$seconds = time();
|
||||
}
|
||||
|
||||
if ($this->mongo instanceof \MongoDB\Client) {
|
||||
return new \MongoDB\BSON\UTCDateTime($seconds * 1000);
|
||||
}
|
||||
|
||||
return new \MongoDate($seconds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class NativeFileSessionHandler extends NativeSessionHandler
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $savePath Path of directory to save session files.
|
||||
* @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
|
||||
*
|
||||
|
|
|
@ -325,14 +325,8 @@ class PdoSessionHandler implements \SessionHandlerInterface
|
|||
|
||||
try {
|
||||
// We use a single MERGE SQL query when supported by the database.
|
||||
$mergeSql = $this->getMergeSql();
|
||||
|
||||
if (null !== $mergeSql) {
|
||||
$mergeStmt = $this->pdo->prepare($mergeSql);
|
||||
$mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
|
||||
$mergeStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
|
||||
$mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime);
|
||||
if (null !== $mergeStmt) {
|
||||
$mergeStmt->execute();
|
||||
|
||||
return true;
|
||||
|
@ -347,7 +341,7 @@ class PdoSessionHandler implements \SessionHandlerInterface
|
|||
$updateStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$updateStmt->execute();
|
||||
|
||||
// When MERGE is not supported, like in Postgres, we have to use this approach that can result in
|
||||
// When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in
|
||||
// duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior).
|
||||
// We can just catch such an error and re-execute the update. This is similar to a serializable
|
||||
// transaction with retry logic on serialization failures but without the overhead and without possible
|
||||
|
@ -510,54 +504,51 @@ class PdoSessionHandler implements \SessionHandlerInterface
|
|||
$selectSql = $this->getSelectSql();
|
||||
$selectStmt = $this->pdo->prepare($selectSql);
|
||||
$selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$selectStmt->execute();
|
||||
|
||||
$sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM);
|
||||
do {
|
||||
$selectStmt->execute();
|
||||
$sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM);
|
||||
|
||||
if ($sessionRows) {
|
||||
if ($sessionRows[0][1] + $sessionRows[0][2] < time()) {
|
||||
$this->sessionExpired = true;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0];
|
||||
}
|
||||
|
||||
if (self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
||||
// Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
|
||||
// until other connections to the session are committed.
|
||||
try {
|
||||
$insertStmt = $this->pdo->prepare(
|
||||
"INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"
|
||||
);
|
||||
$insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$insertStmt->bindValue(':data', '', \PDO::PARAM_LOB);
|
||||
$insertStmt->bindValue(':lifetime', 0, \PDO::PARAM_INT);
|
||||
$insertStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$insertStmt->execute();
|
||||
} catch (\PDOException $e) {
|
||||
// Catch duplicate key error because other connection created the session already.
|
||||
// It would only not be the case when the other connection destroyed the session.
|
||||
if (0 === strpos($e->getCode(), '23')) {
|
||||
// Retrieve finished session data written by concurrent connection. SELECT
|
||||
// FOR UPDATE is necessary to avoid deadlock of connection that starts reading
|
||||
// before we write (transform intention to real lock).
|
||||
$selectStmt->execute();
|
||||
$sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM);
|
||||
|
||||
if ($sessionRows) {
|
||||
return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0];
|
||||
}
|
||||
if ($sessionRows) {
|
||||
if ($sessionRows[0][1] + $sessionRows[0][2] < time()) {
|
||||
$this->sessionExpired = true;
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
throw $e;
|
||||
return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
if (self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
||||
// Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
|
||||
// until other connections to the session are committed.
|
||||
try {
|
||||
$insertStmt = $this->pdo->prepare(
|
||||
"INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"
|
||||
);
|
||||
$insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$insertStmt->bindValue(':data', '', \PDO::PARAM_LOB);
|
||||
$insertStmt->bindValue(':lifetime', 0, \PDO::PARAM_INT);
|
||||
$insertStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$insertStmt->execute();
|
||||
} catch (\PDOException $e) {
|
||||
// Catch duplicate key error because other connection created the session already.
|
||||
// It would only not be the case when the other connection destroyed the session.
|
||||
if (0 === strpos($e->getCode(), '23')) {
|
||||
// Retrieve finished session data written by concurrent connection by restarting the loop.
|
||||
// We have to start a new transaction as a failed query will mark the current transaction as
|
||||
// aborted in PostgreSQL and disallow further queries within it.
|
||||
$this->rollback();
|
||||
$this->beginTransaction();
|
||||
continue;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -653,29 +644,64 @@ class PdoSessionHandler implements \SessionHandlerInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a merge/upsert (i.e. insert or update) SQL query when supported by the database for writing session data.
|
||||
* Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data.
|
||||
*
|
||||
* @return string|null The SQL string or null when not supported
|
||||
* @param string $sessionId Session ID
|
||||
* @param string $data Encoded session data
|
||||
* @param int $maxlifetime session.gc_maxlifetime
|
||||
*
|
||||
* @return \PDOStatement|null The merge statement or null when not supported
|
||||
*/
|
||||
private function getMergeSql()
|
||||
private function getMergeStatement($sessionId, $data, $maxlifetime)
|
||||
{
|
||||
switch ($this->driver) {
|
||||
case 'mysql':
|
||||
return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ".
|
||||
$mergeSql = null;
|
||||
switch (true) {
|
||||
case 'mysql' === $this->driver:
|
||||
$mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ".
|
||||
"ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)";
|
||||
case 'oci':
|
||||
break;
|
||||
case 'oci' === $this->driver:
|
||||
// DUAL is Oracle specific dummy table
|
||||
return "MERGE INTO $this->table USING DUAL ON ($this->idCol = :id) ".
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ".
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time";
|
||||
$mergeSql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ".
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ".
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?";
|
||||
break;
|
||||
case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='):
|
||||
// MERGE is only available since SQL Server 2008 and must be terminated by semicolon
|
||||
// It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
|
||||
return "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = :id) ".
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ".
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time;";
|
||||
case 'sqlite':
|
||||
return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)";
|
||||
$mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ".
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ".
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;";
|
||||
break;
|
||||
case 'sqlite' === $this->driver:
|
||||
$mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)";
|
||||
break;
|
||||
case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='):
|
||||
$mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ".
|
||||
"ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)";
|
||||
break;
|
||||
}
|
||||
|
||||
if (null !== $mergeSql) {
|
||||
$mergeStmt = $this->pdo->prepare($mergeSql);
|
||||
|
||||
if ('sqlsrv' === $this->driver || 'oci' === $this->driver) {
|
||||
$mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB);
|
||||
$mergeStmt->bindParam(4, $maxlifetime, \PDO::PARAM_INT);
|
||||
$mergeStmt->bindValue(5, time(), \PDO::PARAM_INT);
|
||||
$mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB);
|
||||
$mergeStmt->bindParam(7, $maxlifetime, \PDO::PARAM_INT);
|
||||
$mergeStmt->bindValue(8, time(), \PDO::PARAM_INT);
|
||||
} else {
|
||||
$mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
|
||||
$mergeStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
|
||||
$mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
return $mergeStmt;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ class MetadataBag implements SessionBagInterface
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $storageKey The key used to store bag in the session.
|
||||
* @param string $storageKey The key used to store bag in the session
|
||||
* @param int $updateThreshold The time to wait between two UPDATED updates
|
||||
*/
|
||||
public function __construct($storageKey = '_sf2_meta', $updateThreshold = 0)
|
||||
|
|
|
@ -66,7 +66,7 @@ class MockArraySessionStorage implements SessionStorageInterface
|
|||
* Constructor.
|
||||
*
|
||||
* @param string $name Session name
|
||||
* @param MetadataBag $metaBag MetadataBag instance.
|
||||
* @param MetadataBag $metaBag MetadataBag instance
|
||||
*/
|
||||
public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null)
|
||||
{
|
||||
|
|
|
@ -32,9 +32,9 @@ class MockFileSessionStorage extends MockArraySessionStorage
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $savePath Path of directory to save session files.
|
||||
* @param string $name Session name.
|
||||
* @param MetadataBag $metaBag MetadataBag instance.
|
||||
* @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', MetadataBag $metaBag = null)
|
||||
{
|
||||
|
|
|
@ -92,9 +92,9 @@ 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 array $options Session configuration options
|
||||
* @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
|
||||
* @param MetadataBag $metaBag MetadataBag.
|
||||
* @param MetadataBag $metaBag MetadataBag
|
||||
*/
|
||||
public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
|
||||
{
|
||||
|
@ -319,7 +319,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
* For convenience we omit 'session.' from the beginning of the keys.
|
||||
* Explicitly ignores other ini keys.
|
||||
*
|
||||
* @param array $options Session ini directives array(key => value).
|
||||
* @param array $options Session ini directives array(key => value)
|
||||
*
|
||||
* @see http://php.net/session.configuration
|
||||
*/
|
||||
|
|
|
@ -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 bool False
|
||||
*/
|
||||
public function isWrapper()
|
||||
{
|
||||
|
|
|
@ -24,23 +24,23 @@ interface SessionStorageInterface
|
|||
/**
|
||||
* Starts the session.
|
||||
*
|
||||
* @throws \RuntimeException If something goes wrong starting the session.
|
||||
* @return bool True if started
|
||||
*
|
||||
* @return bool True if started.
|
||||
* @throws \RuntimeException If something goes wrong starting the session.
|
||||
*/
|
||||
public function start();
|
||||
|
||||
/**
|
||||
* Checks if the session is started.
|
||||
*
|
||||
* @return bool True if started, false otherwise.
|
||||
* @return bool True if started, false otherwise
|
||||
*/
|
||||
public function isStarted();
|
||||
|
||||
/**
|
||||
* Returns the session ID.
|
||||
*
|
||||
* @return string The session ID or empty.
|
||||
* @return string The session ID or empty
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
|
@ -54,7 +54,7 @@ interface SessionStorageInterface
|
|||
/**
|
||||
* Returns the session name.
|
||||
*
|
||||
* @return mixed The session name.
|
||||
* @return mixed The session name
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
|
|
Reference in a new issue