updated backend
This commit is contained in:
parent
1fea0f4fe7
commit
11521c2339
3459 changed files with 72735 additions and 168535 deletions
|
|
@ -19,12 +19,12 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta
|
|||
private $name = 'attributes';
|
||||
private $storageKey;
|
||||
|
||||
protected $attributes = array();
|
||||
protected $attributes = [];
|
||||
|
||||
/**
|
||||
* @param string $storageKey The key used to store attributes in the session
|
||||
*/
|
||||
public function __construct($storageKey = '_sf2_attributes')
|
||||
public function __construct(string $storageKey = '_sf2_attributes')
|
||||
{
|
||||
$this->storageKey = $storageKey;
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta
|
|||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return array_key_exists($name, $this->attributes);
|
||||
return \array_key_exists($name, $this->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,7 +71,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta
|
|||
*/
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
|
||||
return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -95,7 +95,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta
|
|||
*/
|
||||
public function replace(array $attributes)
|
||||
{
|
||||
$this->attributes = array();
|
||||
$this->attributes = [];
|
||||
foreach ($attributes as $key => $value) {
|
||||
$this->set($key, $value);
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta
|
|||
public function remove($name)
|
||||
{
|
||||
$retval = null;
|
||||
if (array_key_exists($name, $this->attributes)) {
|
||||
if (\array_key_exists($name, $this->attributes)) {
|
||||
$retval = $this->attributes[$name];
|
||||
unset($this->attributes[$name]);
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta
|
|||
public function clear()
|
||||
{
|
||||
$return = $this->attributes;
|
||||
$this->attributes = array();
|
||||
$this->attributes = [];
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,15 +50,10 @@ interface AttributeBagInterface extends SessionBagInterface
|
|||
/**
|
||||
* Returns attributes.
|
||||
*
|
||||
* @return array Attributes
|
||||
* @return array
|
||||
*/
|
||||
public function all();
|
||||
|
||||
/**
|
||||
* Sets attributes.
|
||||
*
|
||||
* @param array $attributes Attributes
|
||||
*/
|
||||
public function replace(array $attributes);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
* @param string $storageKey Session storage key
|
||||
* @param string $namespaceCharacter Namespace character to use in keys
|
||||
*/
|
||||
public function __construct($storageKey = '_sf2_attributes', $namespaceCharacter = '/')
|
||||
public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/')
|
||||
{
|
||||
$this->namespaceCharacter = $namespaceCharacter;
|
||||
parent::__construct($storageKey);
|
||||
|
|
@ -44,7 +44,7 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
return false;
|
||||
}
|
||||
|
||||
return array_key_exists($name, $attributes);
|
||||
return \array_key_exists($name, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -60,7 +60,7 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
return $default;
|
||||
}
|
||||
|
||||
return array_key_exists($name, $attributes) ? $attributes[$name] : $default;
|
||||
return \array_key_exists($name, $attributes) ? $attributes[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,7 +81,7 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
$retval = null;
|
||||
$attributes = &$this->resolveAttributePath($name);
|
||||
$name = $this->resolveKey($name);
|
||||
if (null !== $attributes && array_key_exists($name, $attributes)) {
|
||||
if (null !== $attributes && \array_key_exists($name, $attributes)) {
|
||||
$retval = $attributes[$name];
|
||||
unset($attributes[$name]);
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
* @param string $name Key name
|
||||
* @param bool $writeContext Write context, default false
|
||||
*
|
||||
* @return array
|
||||
* @return array|null
|
||||
*/
|
||||
protected function &resolveAttributePath($name, $writeContext = false)
|
||||
{
|
||||
|
|
@ -115,7 +115,7 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
return $array;
|
||||
}
|
||||
|
||||
$array[$parts[0]] = array();
|
||||
$array[$parts[0]] = [];
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
|
@ -123,14 +123,14 @@ class NamespacedAttributeBag extends AttributeBag
|
|||
unset($parts[\count($parts) - 1]);
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if (null !== $array && !array_key_exists($part, $array)) {
|
||||
if (null !== $array && !\array_key_exists($part, $array)) {
|
||||
if (!$writeContext) {
|
||||
$null = null;
|
||||
|
||||
return $null;
|
||||
}
|
||||
|
||||
$array[$part] = array();
|
||||
$array[$part] = [];
|
||||
}
|
||||
|
||||
$array = &$array[$part];
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ namespace Symfony\Component\HttpFoundation\Session\Flash;
|
|||
class AutoExpireFlashBag implements FlashBagInterface
|
||||
{
|
||||
private $name = 'flashes';
|
||||
private $flashes = array('display' => array(), 'new' => array());
|
||||
private $flashes = ['display' => [], 'new' => []];
|
||||
private $storageKey;
|
||||
|
||||
/**
|
||||
* @param string $storageKey The key used to store flashes in the session
|
||||
*/
|
||||
public function __construct($storageKey = '_symfony_flashes')
|
||||
public function __construct(string $storageKey = '_symfony_flashes')
|
||||
{
|
||||
$this->storageKey = $storageKey;
|
||||
}
|
||||
|
|
@ -53,8 +53,8 @@ class AutoExpireFlashBag implements FlashBagInterface
|
|||
// The logic: messages from the last request will be stored in new, so we move them to previous
|
||||
// This request we will show what is in 'display'. What is placed into 'new' this time round will
|
||||
// be moved to display next time round.
|
||||
$this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : array();
|
||||
$this->flashes['new'] = array();
|
||||
$this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : [];
|
||||
$this->flashes['new'] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -68,7 +68,7 @@ class AutoExpireFlashBag implements FlashBagInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function peek($type, array $default = array())
|
||||
public function peek($type, array $default = [])
|
||||
{
|
||||
return $this->has($type) ? $this->flashes['display'][$type] : $default;
|
||||
}
|
||||
|
|
@ -78,13 +78,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'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($type, array $default = array())
|
||||
public function get($type, array $default = [])
|
||||
{
|
||||
$return = $default;
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ class AutoExpireFlashBag implements FlashBagInterface
|
|||
public function all()
|
||||
{
|
||||
$return = $this->flashes['display'];
|
||||
$this->flashes['display'] = array();
|
||||
$this->flashes['display'] = [];
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ class AutoExpireFlashBag implements FlashBagInterface
|
|||
*/
|
||||
public function has($type)
|
||||
{
|
||||
return array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type];
|
||||
return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ namespace Symfony\Component\HttpFoundation\Session\Flash;
|
|||
class FlashBag implements FlashBagInterface
|
||||
{
|
||||
private $name = 'flashes';
|
||||
private $flashes = array();
|
||||
private $flashes = [];
|
||||
private $storageKey;
|
||||
|
||||
/**
|
||||
* @param string $storageKey The key used to store flashes in the session
|
||||
*/
|
||||
public function __construct($storageKey = '_symfony_flashes')
|
||||
public function __construct(string $storageKey = '_symfony_flashes')
|
||||
{
|
||||
$this->storageKey = $storageKey;
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ class FlashBag implements FlashBagInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function peek($type, array $default = array())
|
||||
public function peek($type, array $default = [])
|
||||
{
|
||||
return $this->has($type) ? $this->flashes[$type] : $default;
|
||||
}
|
||||
|
|
@ -78,7 +78,7 @@ class FlashBag implements FlashBagInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($type, array $default = array())
|
||||
public function get($type, array $default = [])
|
||||
{
|
||||
if (!$this->has($type)) {
|
||||
return $default;
|
||||
|
|
@ -97,7 +97,7 @@ class FlashBag implements FlashBagInterface
|
|||
public function all()
|
||||
{
|
||||
$return = $this->peekAll();
|
||||
$this->flashes = array();
|
||||
$this->flashes = [];
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ class FlashBag implements FlashBagInterface
|
|||
*/
|
||||
public function has($type)
|
||||
{
|
||||
return array_key_exists($type, $this->flashes) && $this->flashes[$type];
|
||||
return \array_key_exists($type, $this->flashes) && $this->flashes[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
|||
interface FlashBagInterface extends SessionBagInterface
|
||||
{
|
||||
/**
|
||||
* Adds a flash message for type.
|
||||
* Adds a flash message for the given type.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $message
|
||||
|
|
@ -29,12 +29,12 @@ interface FlashBagInterface extends SessionBagInterface
|
|||
public function add($type, $message);
|
||||
|
||||
/**
|
||||
* Registers a message for a given type.
|
||||
* Registers one or more messages for a given type.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string|array $message
|
||||
* @param string|array $messages
|
||||
*/
|
||||
public function set($type, $message);
|
||||
public function set($type, $messages);
|
||||
|
||||
/**
|
||||
* Gets flash messages for a given type.
|
||||
|
|
@ -44,7 +44,7 @@ interface FlashBagInterface extends SessionBagInterface
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function peek($type, array $default = array());
|
||||
public function peek($type, array $default = []);
|
||||
|
||||
/**
|
||||
* Gets all flash messages.
|
||||
|
|
@ -61,7 +61,7 @@ interface FlashBagInterface extends SessionBagInterface
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get($type, array $default = array());
|
||||
public function get($type, array $default = []);
|
||||
|
||||
/**
|
||||
* Gets and clears flashes from the stack.
|
||||
|
|
|
|||
|
|
@ -28,14 +28,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
|||
|
||||
private $flashName;
|
||||
private $attributeName;
|
||||
private $data = array();
|
||||
private $data = [];
|
||||
private $usageIndex = 0;
|
||||
|
||||
/**
|
||||
* @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)
|
||||
*/
|
||||
public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null)
|
||||
{
|
||||
$this->storage = $storage ?: new NativeSessionStorage();
|
||||
|
|
@ -134,29 +129,22 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
|||
/**
|
||||
* Returns the number of attributes.
|
||||
*
|
||||
* @return int The number of attributes
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return \count($this->getAttributeBag()->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function getUsageIndex()
|
||||
public function &getUsageIndex(): int
|
||||
{
|
||||
return $this->usageIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function isEmpty()
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
if ($this->isStarted()) {
|
||||
++$this->usageIndex;
|
||||
|
|
@ -209,7 +197,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
|||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->storage->setId($id);
|
||||
if ($this->storage->getId() !== $id) {
|
||||
$this->storage->setId($id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -251,7 +241,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
|||
*/
|
||||
public function getBag($name)
|
||||
{
|
||||
return $this->storage->getBag($name)->getBag();
|
||||
$bag = $this->storage->getBag($name);
|
||||
|
||||
return method_exists($bag, 'getBag') ? $bag->getBag() : $bag;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -268,10 +260,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
|||
* Gets the attributebag interface.
|
||||
*
|
||||
* Note that this method was added to help with IDE autocompletion.
|
||||
*
|
||||
* @return AttributeBagInterface
|
||||
*/
|
||||
private function getAttributeBag()
|
||||
private function getAttributeBag(): AttributeBagInterface
|
||||
{
|
||||
return $this->getBag($this->attributeName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ interface SessionInterface
|
|||
/**
|
||||
* Starts the session storage.
|
||||
*
|
||||
* @return bool True if session started
|
||||
* @return bool
|
||||
*
|
||||
* @throws \RuntimeException if session fails to start
|
||||
*/
|
||||
|
|
@ -32,7 +32,7 @@ interface SessionInterface
|
|||
/**
|
||||
* Returns the session ID.
|
||||
*
|
||||
* @return string The session ID
|
||||
* @return string
|
||||
*/
|
||||
public function getId();
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ interface SessionInterface
|
|||
/**
|
||||
* Returns the session name.
|
||||
*
|
||||
* @return mixed The session name
|
||||
* @return string
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public function invalidate($lifetime = null);
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ interface SessionInterface
|
|||
* 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
|
||||
*/
|
||||
public function migrate($destroy = false, $lifetime = null);
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ interface SessionInterface
|
|||
*
|
||||
* @param string $name The attribute name
|
||||
*
|
||||
* @return bool true if the attribute is defined, false otherwise
|
||||
* @return bool
|
||||
*/
|
||||
public function has($name);
|
||||
|
||||
|
|
@ -125,14 +125,12 @@ interface SessionInterface
|
|||
/**
|
||||
* Returns attributes.
|
||||
*
|
||||
* @return array Attributes
|
||||
* @return array
|
||||
*/
|
||||
public function all();
|
||||
|
||||
/**
|
||||
* Sets attributes.
|
||||
*
|
||||
* @param array $attributes Attributes
|
||||
*/
|
||||
public function replace(array $attributes);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,120 +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;
|
||||
|
||||
@trigger_error(sprintf('The class %s is deprecated since Symfony 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead.', MemcacheSessionHandler::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* @author Drak <drak@zikula.org>
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead.
|
||||
*/
|
||||
class MemcacheSessionHandler implements \SessionHandlerInterface
|
||||
{
|
||||
private $memcache;
|
||||
|
||||
/**
|
||||
* @var int Time to live in seconds
|
||||
*/
|
||||
private $ttl;
|
||||
|
||||
/**
|
||||
* @var string Key prefix for shared environments
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* 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 $options = array())
|
||||
{
|
||||
if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The following options are not supported "%s"', implode(', ', $diff)
|
||||
));
|
||||
}
|
||||
|
||||
$this->memcache = $memcache;
|
||||
$this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400;
|
||||
$this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($sessionId)
|
||||
{
|
||||
return $this->memcache->get($this->prefix.$sessionId) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($sessionId, $data)
|
||||
{
|
||||
return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
$this->memcache->delete($this->prefix.$sessionId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
// not required here because memcache will auto expire the records anyhow.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Memcache instance.
|
||||
*
|
||||
* @return \Memcache
|
||||
*/
|
||||
protected function getMemcache()
|
||||
{
|
||||
return $this->memcache;
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
* Memcached based session storage handler based on the Memcached class
|
||||
* provided by the PHP memcached extension.
|
||||
*
|
||||
* @see http://php.net/memcached
|
||||
* @see https://php.net/memcached
|
||||
*
|
||||
* @author Drak <drak@zikula.org>
|
||||
*/
|
||||
|
|
@ -40,19 +40,14 @@ class MemcachedSessionHandler extends AbstractSessionHandler
|
|||
* * 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 $options = array())
|
||||
public function __construct(\Memcached $memcached, array $options = [])
|
||||
{
|
||||
$this->memcached = $memcached;
|
||||
|
||||
if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The following options are not supported "%s"', implode(', ', $diff)
|
||||
));
|
||||
if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime'])) {
|
||||
throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff)));
|
||||
}
|
||||
|
||||
$this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400;
|
||||
|
|
@ -60,11 +55,11 @@ class MemcachedSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return true;
|
||||
return $this->memcached->quit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,7 +71,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function updateTimestamp($sessionId, $data)
|
||||
{
|
||||
|
|
@ -104,7 +99,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,14 +17,14 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
* @author Markus Bachmann <markus.bachmann@bachi.biz>
|
||||
*
|
||||
* @see https://packagist.org/packages/mongodb/mongodb
|
||||
* @see http://php.net/manual/en/set.mongodb.php
|
||||
* @see https://php.net/mongodb
|
||||
*/
|
||||
class MongoDbSessionHandler extends AbstractSessionHandler
|
||||
{
|
||||
private $mongo;
|
||||
|
||||
/**
|
||||
* @var \MongoCollection
|
||||
* @var \MongoDB\Collection
|
||||
*/
|
||||
private $collection;
|
||||
|
||||
|
|
@ -56,43 +56,31 @@ class MongoDbSessionHandler extends AbstractSessionHandler
|
|||
* { "expireAfterSeconds": 0 }
|
||||
* )
|
||||
*
|
||||
* More details on: http://docs.mongodb.org/manual/tutorial/expire-data/
|
||||
* More details on: https://docs.mongodb.org/manual/tutorial/expire-data/
|
||||
*
|
||||
* If you use such an index, you can drop `gc_probability` to 0 since
|
||||
* no garbage-collection is required.
|
||||
*
|
||||
* @param \MongoDB\Client $mongo A MongoDB\Client 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)
|
||||
public function __construct(\MongoDB\Client $mongo, array $options)
|
||||
{
|
||||
if ($mongo instanceof \MongoClient || $mongo instanceof \Mongo) {
|
||||
@trigger_error(sprintf('Using %s with the legacy mongo extension is deprecated as of 3.4 and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead.', __CLASS__), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (!($mongo instanceof \MongoDB\Client || $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(
|
||||
$this->options = array_merge([
|
||||
'id_field' => '_id',
|
||||
'data_field' => 'data',
|
||||
'time_field' => 'time',
|
||||
'expiry_field' => 'expires_at',
|
||||
), $options);
|
||||
], $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
|
|
@ -104,25 +92,21 @@ class MongoDbSessionHandler extends AbstractSessionHandler
|
|||
*/
|
||||
protected function doDestroy($sessionId)
|
||||
{
|
||||
$methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove';
|
||||
|
||||
$this->getCollection()->$methodName(array(
|
||||
$this->getCollection()->deleteOne([
|
||||
$this->options['id_field'] => $sessionId,
|
||||
));
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
$methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteMany' : 'remove';
|
||||
|
||||
$this->getCollection()->$methodName(array(
|
||||
$this->options['expiry_field'] => array('$lt' => $this->createDateTime()),
|
||||
));
|
||||
$this->getCollection()->deleteMany([
|
||||
$this->options['expiry_field'] => ['$lt' => new \MongoDB\BSON\UTCDateTime()],
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -132,55 +116,36 @@ class MongoDbSessionHandler extends AbstractSessionHandler
|
|||
*/
|
||||
protected function doWrite($sessionId, $data)
|
||||
{
|
||||
$expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime'));
|
||||
$expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000);
|
||||
|
||||
$fields = array(
|
||||
$this->options['time_field'] => $this->createDateTime(),
|
||||
$fields = [
|
||||
$this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(),
|
||||
$this->options['expiry_field'] => $expiry,
|
||||
);
|
||||
$this->options['data_field'] => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY),
|
||||
];
|
||||
|
||||
$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),
|
||||
$options
|
||||
$this->getCollection()->updateOne(
|
||||
[$this->options['id_field'] => $sessionId],
|
||||
['$set' => $fields],
|
||||
['upsert' => true]
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function updateTimestamp($sessionId, $data)
|
||||
{
|
||||
$expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime'));
|
||||
$expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000);
|
||||
|
||||
if ($this->mongo instanceof \MongoDB\Client) {
|
||||
$methodName = 'updateOne';
|
||||
$options = array();
|
||||
} else {
|
||||
$methodName = 'update';
|
||||
$options = array('multiple' => false);
|
||||
}
|
||||
|
||||
$this->getCollection()->$methodName(
|
||||
array($this->options['id_field'] => $sessionId),
|
||||
array('$set' => array(
|
||||
$this->options['time_field'] => $this->createDateTime(),
|
||||
$this->getCollection()->updateOne(
|
||||
[$this->options['id_field'] => $sessionId],
|
||||
['$set' => [
|
||||
$this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(),
|
||||
$this->options['expiry_field'] => $expiry,
|
||||
)),
|
||||
$options
|
||||
]]
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
@ -191,28 +156,19 @@ class MongoDbSessionHandler extends AbstractSessionHandler
|
|||
*/
|
||||
protected function doRead($sessionId)
|
||||
{
|
||||
$dbData = $this->getCollection()->findOne(array(
|
||||
$dbData = $this->getCollection()->findOne([
|
||||
$this->options['id_field'] => $sessionId,
|
||||
$this->options['expiry_field'] => array('$gte' => $this->createDateTime()),
|
||||
));
|
||||
$this->options['expiry_field'] => ['$gte' => new \MongoDB\BSON\UTCDateTime()],
|
||||
]);
|
||||
|
||||
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;
|
||||
return $dbData[$this->options['data_field']]->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a "MongoCollection" instance.
|
||||
*
|
||||
* @return \MongoCollection
|
||||
*/
|
||||
private function getCollection()
|
||||
private function getCollection(): \MongoDB\Collection
|
||||
{
|
||||
if (null === $this->collection) {
|
||||
$this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']);
|
||||
|
|
@ -222,34 +178,10 @@ class MongoDbSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a Mongo instance.
|
||||
*
|
||||
* @return \Mongo|\MongoClient|\MongoDB\Client
|
||||
* @return \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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,19 +16,19 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
*
|
||||
* @author Drak <drak@zikula.org>
|
||||
*/
|
||||
class NativeFileSessionHandler extends NativeSessionHandler
|
||||
class NativeFileSessionHandler extends \SessionHandler
|
||||
{
|
||||
/**
|
||||
* @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.
|
||||
* @see https://php.net/session.configuration#ini.session.save-path for further details.
|
||||
*
|
||||
* @throws \InvalidArgumentException On invalid $savePath
|
||||
* @throws \RuntimeException When failing to create the save directory
|
||||
*/
|
||||
public function __construct($savePath = null)
|
||||
public function __construct(string $savePath = null)
|
||||
{
|
||||
if (null === $savePath) {
|
||||
$savePath = ini_get('session.save_path');
|
||||
|
|
|
|||
|
|
@ -1,24 +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;
|
||||
|
||||
/**
|
||||
* @deprecated since version 3.4, to be removed in 4.0. Use \SessionHandler instead.
|
||||
* @see http://php.net/sessionhandler
|
||||
*/
|
||||
class NativeSessionHandler extends \SessionHandler
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@trigger_error('The '.__NAMESPACE__.'\NativeSessionHandler class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the \SessionHandler class instead.', E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
class NullSessionHandler extends AbstractSessionHandler
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
|
|
@ -27,7 +27,7 @@ class NullSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function validateId($sessionId)
|
||||
{
|
||||
|
|
@ -43,7 +43,7 @@ class NullSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function updateTimestamp($sessionId, $data)
|
||||
{
|
||||
|
|
@ -67,7 +67,7 @@ class NullSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
|
|||
* Saving it in a character column could corrupt the data. You can use createTable()
|
||||
* to initialize a correctly defined table.
|
||||
*
|
||||
* @see http://php.net/sessionhandlerinterface
|
||||
* @see https://php.net/sessionhandlerinterface
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Michael Williams <michael.williams@funsational.com>
|
||||
|
|
@ -65,13 +65,15 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
*/
|
||||
const LOCK_TRANSACTIONAL = 2;
|
||||
|
||||
private const MAX_LIFETIME = 315576000;
|
||||
|
||||
/**
|
||||
* @var \PDO|null PDO instance or null when not connected yet
|
||||
*/
|
||||
private $pdo;
|
||||
|
||||
/**
|
||||
* @var string|null|false DSN string or null for session.save_path or false when lazy connection disabled
|
||||
* @var string|false|null DSN string or null for session.save_path or false when lazy connection disabled
|
||||
*/
|
||||
private $dsn = false;
|
||||
|
||||
|
|
@ -118,7 +120,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
/**
|
||||
* @var array Connection options when lazy-connect
|
||||
*/
|
||||
private $connectionOptions = array();
|
||||
private $connectionOptions = [];
|
||||
|
||||
/**
|
||||
* @var int The strategy for locking, see constants
|
||||
|
|
@ -130,7 +132,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
*
|
||||
* @var \PDOStatement[] An array of statements to release advisory locks
|
||||
*/
|
||||
private $unlockStatements = array();
|
||||
private $unlockStatements = [];
|
||||
|
||||
/**
|
||||
* @var bool True when the current session exists but expired according to session.gc_maxlifetime
|
||||
|
|
@ -161,15 +163,14 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
* * db_time_col: The column where to store the timestamp [default: sess_time]
|
||||
* * db_username: The username when lazy-connect [default: '']
|
||||
* * db_password: The password when lazy-connect [default: '']
|
||||
* * db_connection_options: An array of driver-specific connection options [default: array()]
|
||||
* * db_connection_options: An array of driver-specific connection options [default: []]
|
||||
* * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL]
|
||||
*
|
||||
* @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null
|
||||
* @param array $options An associative array of options
|
||||
*
|
||||
* @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
|
||||
*/
|
||||
public function __construct($pdoOrDsn = null, array $options = array())
|
||||
public function __construct($pdoOrDsn = null, array $options = [])
|
||||
{
|
||||
if ($pdoOrDsn instanceof \PDO) {
|
||||
if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) {
|
||||
|
|
@ -218,7 +219,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
// - trailing space removal
|
||||
// - case-insensitivity
|
||||
// - language processing like é == e
|
||||
$sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol MEDIUMINT NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB";
|
||||
$sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB";
|
||||
break;
|
||||
case 'sqlite':
|
||||
$sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)";
|
||||
|
|
@ -238,6 +239,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
|
||||
try {
|
||||
$this->pdo->exec($sql);
|
||||
$this->pdo->exec("CREATE INDEX EXPIRY ON $this->table ($this->lifetimeCol)");
|
||||
} catch (\PDOException $e) {
|
||||
$this->rollback();
|
||||
|
||||
|
|
@ -258,7 +260,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
|
|
@ -272,7 +274,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return string
|
||||
*/
|
||||
public function read($sessionId)
|
||||
{
|
||||
|
|
@ -286,7 +288,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
|
|
@ -365,18 +367,18 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function updateTimestamp($sessionId, $data)
|
||||
{
|
||||
$maxlifetime = (int) ini_get('session.gc_maxlifetime');
|
||||
$expiry = time() + (int) ini_get('session.gc_maxlifetime');
|
||||
|
||||
try {
|
||||
$updateStmt = $this->pdo->prepare(
|
||||
"UPDATE $this->table SET $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"
|
||||
"UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"
|
||||
);
|
||||
$updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$updateStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
|
||||
$updateStmt->bindParam(':expiry', $expiry, \PDO::PARAM_INT);
|
||||
$updateStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$updateStmt->execute();
|
||||
} catch (\PDOException $e) {
|
||||
|
|
@ -389,7 +391,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
|
|
@ -403,14 +405,21 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
$this->gcCalled = false;
|
||||
|
||||
// delete the session records that have expired
|
||||
if ('mysql' === $this->driver) {
|
||||
$sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol < :time";
|
||||
} else {
|
||||
$sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time - $this->timeCol";
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time AND $this->lifetimeCol > :min";
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
// to be removed in 6.0
|
||||
if ('mysql' === $this->driver) {
|
||||
$legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol + $this->timeCol < :time";
|
||||
} else {
|
||||
$legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol < :time - $this->timeCol";
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare($legacySql);
|
||||
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
|
|
@ -423,10 +432,8 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
|
||||
/**
|
||||
* Lazy-connects to the database.
|
||||
*
|
||||
* @param string $dsn DSN string
|
||||
*/
|
||||
private function connect($dsn)
|
||||
private function connect(string $dsn): void
|
||||
{
|
||||
$this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions);
|
||||
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
|
|
@ -436,13 +443,9 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
/**
|
||||
* Builds a PDO DSN from a URL-like connection string.
|
||||
*
|
||||
* @param string $dsnOrUrl
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @todo implement missing support for oci DSN (which look totally different from other PDO ones)
|
||||
*/
|
||||
private function buildDsnFromUrl($dsnOrUrl)
|
||||
private function buildDsnFromUrl(string $dsnOrUrl): string
|
||||
{
|
||||
// (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid
|
||||
$url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl);
|
||||
|
|
@ -468,13 +471,13 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler');
|
||||
}
|
||||
|
||||
$driverAliasMap = array(
|
||||
$driverAliasMap = [
|
||||
'mssql' => 'sqlsrv',
|
||||
'mysql2' => 'mysql', // Amazon RDS, for some weird reason
|
||||
'postgres' => 'pgsql',
|
||||
'postgresql' => 'pgsql',
|
||||
'sqlite3' => 'sqlite',
|
||||
);
|
||||
];
|
||||
|
||||
$driver = isset($driverAliasMap[$params['scheme']]) ? $driverAliasMap[$params['scheme']] : $params['scheme'];
|
||||
|
||||
|
|
@ -538,10 +541,10 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
* PDO::rollback or PDO::inTransaction for SQLite.
|
||||
*
|
||||
* Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions
|
||||
* due to http://www.mysqlperformanceblog.com/2013/12/12/one-more-innodb-gap-lock-to-avoid/ .
|
||||
* due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ .
|
||||
* So we change it to READ COMMITTED.
|
||||
*/
|
||||
private function beginTransaction()
|
||||
private function beginTransaction(): void
|
||||
{
|
||||
if (!$this->inTransaction) {
|
||||
if ('sqlite' === $this->driver) {
|
||||
|
|
@ -559,7 +562,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
/**
|
||||
* Helper method to commit a transaction.
|
||||
*/
|
||||
private function commit()
|
||||
private function commit(): void
|
||||
{
|
||||
if ($this->inTransaction) {
|
||||
try {
|
||||
|
|
@ -581,7 +584,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
/**
|
||||
* Helper method to rollback a transaction.
|
||||
*/
|
||||
private function rollback()
|
||||
private function rollback(): void
|
||||
{
|
||||
// We only need to rollback if we are in a transaction. Otherwise the resulting
|
||||
// error would hide the real problem why rollback was called. We might not be
|
||||
|
|
@ -623,7 +626,12 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
$sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM);
|
||||
|
||||
if ($sessionRows) {
|
||||
if ($sessionRows[0][1] + $sessionRows[0][2] < time()) {
|
||||
$expiry = (int) $sessionRows[0][1];
|
||||
if ($expiry <= self::MAX_LIFETIME) {
|
||||
$expiry += $sessionRows[0][2];
|
||||
}
|
||||
|
||||
if ($expiry < time()) {
|
||||
$this->sessionExpired = true;
|
||||
|
||||
return '';
|
||||
|
|
@ -637,7 +645,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.');
|
||||
}
|
||||
|
||||
if (!ini_get('session.use_strict_mode') && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
||||
if (!filter_var(ini_get('session.use_strict_mode'), FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
||||
// In strict mode, session fixation is not possible: new sessions always start with a unique
|
||||
// random id, so that concurrency is not possible and this code path can be skipped.
|
||||
// Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
|
||||
|
|
@ -668,8 +676,6 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
/**
|
||||
* Executes an application-level lock on the database.
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
*
|
||||
* @return \PDOStatement The statement that needs to be executed later to release the lock
|
||||
*
|
||||
* @throws \DomainException When an unsupported PDO driver is used
|
||||
|
|
@ -678,12 +684,12 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
* - for oci using DBMS_LOCK.REQUEST
|
||||
* - for sqlsrv using sp_getapplock with LockOwner = Session
|
||||
*/
|
||||
private function doAdvisoryLock($sessionId)
|
||||
private function doAdvisoryLock(string $sessionId): \PDOStatement
|
||||
{
|
||||
switch ($this->driver) {
|
||||
case 'mysql':
|
||||
// MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced.
|
||||
$lockId = \substr($sessionId, 0, 64);
|
||||
$lockId = substr($sessionId, 0, 64);
|
||||
// should we handle the return value? 0 on timeout, null on error
|
||||
// we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout
|
||||
$stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)');
|
||||
|
|
@ -733,12 +739,8 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
* Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer.
|
||||
*
|
||||
* Keep in mind, PHP integers are signed.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function convertStringToInt($string)
|
||||
private function convertStringToInt(string $string): int
|
||||
{
|
||||
if (4 === \PHP_INT_SIZE) {
|
||||
return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]);
|
||||
|
|
@ -753,15 +755,14 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
/**
|
||||
* Return a locking or nonlocking SQL query to read session information.
|
||||
*
|
||||
* @return string The SQL string
|
||||
*
|
||||
* @throws \DomainException When an unsupported PDO driver is used
|
||||
*/
|
||||
private function getSelectSql()
|
||||
private function getSelectSql(): string
|
||||
{
|
||||
if (self::LOCK_TRANSACTIONAL === $this->lockMode) {
|
||||
$this->beginTransaction();
|
||||
|
||||
// selecting the time column should be removed in 6.0
|
||||
switch ($this->driver) {
|
||||
case 'mysql':
|
||||
case 'oci':
|
||||
|
|
@ -782,32 +783,26 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
|
||||
/**
|
||||
* Returns an insert statement supported by the database for writing session data.
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @param string $sessionData Encoded session data
|
||||
* @param int $maxlifetime session.gc_maxlifetime
|
||||
*
|
||||
* @return \PDOStatement The insert statement
|
||||
*/
|
||||
private function getInsertStatement($sessionId, $sessionData, $maxlifetime)
|
||||
private function getInsertStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement
|
||||
{
|
||||
switch ($this->driver) {
|
||||
case 'oci':
|
||||
$data = fopen('php://memory', 'r+');
|
||||
fwrite($data, $sessionData);
|
||||
rewind($data);
|
||||
$sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :lifetime, :time) RETURNING $this->dataCol into :data";
|
||||
$sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data";
|
||||
break;
|
||||
default:
|
||||
$data = $sessionData;
|
||||
$sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)";
|
||||
$sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)";
|
||||
break;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$stmt->bindParam(':data', $data, \PDO::PARAM_LOB);
|
||||
$stmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
|
||||
return $stmt;
|
||||
|
|
@ -815,32 +810,26 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
|
||||
/**
|
||||
* Returns an update statement supported by the database for writing session data.
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @param string $sessionData Encoded session data
|
||||
* @param int $maxlifetime session.gc_maxlifetime
|
||||
*
|
||||
* @return \PDOStatement The update statement
|
||||
*/
|
||||
private function getUpdateStatement($sessionId, $sessionData, $maxlifetime)
|
||||
private function getUpdateStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement
|
||||
{
|
||||
switch ($this->driver) {
|
||||
case 'oci':
|
||||
$data = fopen('php://memory', 'r+');
|
||||
fwrite($data, $sessionData);
|
||||
rewind($data);
|
||||
$sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data";
|
||||
$sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data";
|
||||
break;
|
||||
default:
|
||||
$data = $sessionData;
|
||||
$sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id";
|
||||
$sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id";
|
||||
break;
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$stmt->bindParam(':data', $data, \PDO::PARAM_LOB);
|
||||
$stmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
|
||||
return $stmt;
|
||||
|
|
@ -848,36 +837,30 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
|
||||
/**
|
||||
* Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data.
|
||||
*
|
||||
* @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 getMergeStatement($sessionId, $data, $maxlifetime)
|
||||
private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement
|
||||
{
|
||||
switch (true) {
|
||||
case 'mysql' === $this->driver:
|
||||
$mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ".
|
||||
$mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ".
|
||||
"ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($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
|
||||
// It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/
|
||||
$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)";
|
||||
$mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :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) ".
|
||||
$mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ".
|
||||
"ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)";
|
||||
break;
|
||||
default:
|
||||
// MERGE is not supported with LOBs: http://www.oracle.com/technetwork/articles/fuecks-lobs-095315.html
|
||||
// MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -887,15 +870,15 @@ class PdoSessionHandler extends AbstractSessionHandler
|
|||
$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(4, time() + $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(7, time() + $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(':expiry', time() + $maxlifetime, \PDO::PARAM_INT);
|
||||
$mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,92 +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;
|
||||
|
||||
/**
|
||||
* Wraps another SessionHandlerInterface to only write the session when it has been modified.
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0. Implement `SessionUpdateTimestampHandlerInterface` or extend `AbstractSessionHandler` instead.
|
||||
*/
|
||||
class WriteCheckSessionHandler implements \SessionHandlerInterface
|
||||
{
|
||||
private $wrappedSessionHandler;
|
||||
|
||||
/**
|
||||
* @var array sessionId => session
|
||||
*/
|
||||
private $readSessions;
|
||||
|
||||
public function __construct(\SessionHandlerInterface $wrappedSessionHandler)
|
||||
{
|
||||
@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Implement `SessionUpdateTimestampHandlerInterface` or extend `AbstractSessionHandler` instead.', self::class), E_USER_DEPRECATED);
|
||||
|
||||
$this->wrappedSessionHandler = $wrappedSessionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return $this->wrappedSessionHandler->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
return $this->wrappedSessionHandler->destroy($sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
return $this->wrappedSessionHandler->gc($maxlifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
return $this->wrappedSessionHandler->open($savePath, $sessionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($sessionId)
|
||||
{
|
||||
$session = $this->wrappedSessionHandler->read($sessionId);
|
||||
|
||||
$this->readSessions[$sessionId] = $session;
|
||||
|
||||
return $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($sessionId, $data)
|
||||
{
|
||||
if (isset($this->readSessions[$sessionId]) && $data === $this->readSessions[$sessionId]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->wrappedSessionHandler->write($sessionId, $data);
|
||||
}
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ class MetadataBag implements SessionBagInterface
|
|||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0);
|
||||
protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0];
|
||||
|
||||
/**
|
||||
* Unix timestamp.
|
||||
|
|
@ -57,7 +57,7 @@ class MetadataBag implements SessionBagInterface
|
|||
* @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)
|
||||
public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0)
|
||||
{
|
||||
$this->storageKey = $storageKey;
|
||||
$this->updateThreshold = $updateThreshold;
|
||||
|
|
@ -159,7 +159,7 @@ class MetadataBag implements SessionBagInterface
|
|||
$this->name = $name;
|
||||
}
|
||||
|
||||
private function stampCreated($lifetime = null)
|
||||
private function stampCreated(int $lifetime = null): void
|
||||
{
|
||||
$timeStamp = time();
|
||||
$this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class MockArraySessionStorage implements SessionStorageInterface
|
|||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = array();
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* @var MetadataBag
|
||||
|
|
@ -60,13 +60,9 @@ class MockArraySessionStorage implements SessionStorageInterface
|
|||
/**
|
||||
* @var array|SessionBagInterface[]
|
||||
*/
|
||||
protected $bags = array();
|
||||
protected $bags = [];
|
||||
|
||||
/**
|
||||
* @param string $name Session name
|
||||
* @param MetadataBag $metaBag MetadataBag instance
|
||||
*/
|
||||
public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null)
|
||||
public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->setMetadataBag($metaBag);
|
||||
|
|
@ -170,7 +166,7 @@ class MockArraySessionStorage implements SessionStorageInterface
|
|||
}
|
||||
|
||||
// clear out the session
|
||||
$this->data = array();
|
||||
$this->data = [];
|
||||
|
||||
// reconnect the bags to the session
|
||||
$this->loadSession();
|
||||
|
|
@ -242,11 +238,11 @@ class MockArraySessionStorage implements SessionStorageInterface
|
|||
|
||||
protected function loadSession()
|
||||
{
|
||||
$bags = array_merge($this->bags, array($this->metadataBag));
|
||||
$bags = array_merge($this->bags, [$this->metadataBag]);
|
||||
|
||||
foreach ($bags as $bag) {
|
||||
$key = $bag->getStorageKey();
|
||||
$this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array();
|
||||
$this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : [];
|
||||
$bag->initialize($this->data[$key]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,11 +27,10 @@ class MockFileSessionStorage extends MockArraySessionStorage
|
|||
private $savePath;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null)
|
||||
public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null)
|
||||
{
|
||||
if (null === $savePath) {
|
||||
$savePath = sys_get_temp_dir();
|
||||
|
|
@ -98,7 +97,7 @@ class MockFileSessionStorage extends MockArraySessionStorage
|
|||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
if (array($key = $this->metadataBag->getStorageKey()) === array_keys($data)) {
|
||||
if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +121,7 @@ class MockFileSessionStorage extends MockArraySessionStorage
|
|||
* Deletes a session from persistent storage.
|
||||
* Deliberately leaves session data in memory intact.
|
||||
*/
|
||||
private function destroy()
|
||||
private function destroy(): void
|
||||
{
|
||||
if (is_file($this->getFilePath())) {
|
||||
unlink($this->getFilePath());
|
||||
|
|
@ -131,10 +130,8 @@ class MockFileSessionStorage extends MockArraySessionStorage
|
|||
|
||||
/**
|
||||
* Calculate path to file.
|
||||
*
|
||||
* @return string File path
|
||||
*/
|
||||
private function getFilePath()
|
||||
private function getFilePath(): string
|
||||
{
|
||||
return $this->savePath.'/'.$this->id.'.mocksess';
|
||||
}
|
||||
|
|
@ -142,10 +139,10 @@ class MockFileSessionStorage extends MockArraySessionStorage
|
|||
/**
|
||||
* Reads session from storage and loads session.
|
||||
*/
|
||||
private function read()
|
||||
private function read(): void
|
||||
{
|
||||
$filePath = $this->getFilePath();
|
||||
$this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array();
|
||||
$this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : [];
|
||||
|
||||
$this->loadSession();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
namespace Symfony\Component\HttpFoundation\Session\Storage;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionUtils;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
|
||||
|
|
@ -26,7 +27,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
/**
|
||||
* @var SessionBagInterface[]
|
||||
*/
|
||||
protected $bags = array();
|
||||
protected $bags = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
|
|
@ -48,13 +49,18 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
*/
|
||||
protected $metadataBag;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $emulateSameSite;
|
||||
|
||||
/**
|
||||
* Depending on how you want the storage driver to behave you probably
|
||||
* want to override this constructor entirely.
|
||||
*
|
||||
* List of options for $options array with their defaults.
|
||||
*
|
||||
* @see http://php.net/session.configuration for options
|
||||
* @see https://php.net/session.configuration for options
|
||||
* but we omit 'session.' from the beginning of the keys for convenience.
|
||||
*
|
||||
* ("auto_start", is not supported as it tells PHP to start a session before
|
||||
|
|
@ -67,13 +73,10 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
* cookie_lifetime, "0"
|
||||
* cookie_path, "/"
|
||||
* cookie_secure, ""
|
||||
* entropy_file, ""
|
||||
* entropy_length, "0"
|
||||
* cookie_samesite, null
|
||||
* gc_divisor, "100"
|
||||
* gc_maxlifetime, "1440"
|
||||
* gc_probability, "1"
|
||||
* hash_bits_per_character, "4"
|
||||
* hash_function, "0"
|
||||
* lazy_write, "1"
|
||||
* name, "PHPSESSID"
|
||||
* referer_check, ""
|
||||
|
|
@ -94,18 +97,21 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
* trans_sid_hosts, $_SERVER['HTTP_HOST']
|
||||
* trans_sid_tags, "a=href,area=href,frame=src,form="
|
||||
*
|
||||
* @param array $options Session configuration options
|
||||
* @param \SessionHandlerInterface|null $handler
|
||||
* @param MetadataBag $metaBag MetadataBag
|
||||
* @param AbstractProxy|\SessionHandlerInterface|null $handler
|
||||
*/
|
||||
public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
|
||||
public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null)
|
||||
{
|
||||
$options += array(
|
||||
if (!\extension_loaded('session')) {
|
||||
throw new \LogicException('PHP extension "session" is required.');
|
||||
}
|
||||
|
||||
$options += [
|
||||
'cache_limiter' => '',
|
||||
'cache_expire' => 0,
|
||||
'use_cookies' => 1,
|
||||
'lazy_write' => 1,
|
||||
);
|
||||
'use_strict_mode' => 1,
|
||||
];
|
||||
|
||||
session_register_shutdown();
|
||||
|
||||
|
|
@ -137,7 +143,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
throw new \RuntimeException('Failed to start the session: already started by PHP.');
|
||||
}
|
||||
|
||||
if (ini_get('session.use_cookies') && headers_sent($file, $line)) {
|
||||
if (filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) {
|
||||
throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
|
||||
}
|
||||
|
||||
|
|
@ -146,6 +152,13 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
throw new \RuntimeException('Failed to start the session');
|
||||
}
|
||||
|
||||
if (null !== $this->emulateSameSite) {
|
||||
$originalCookie = SessionUtils::popSessionCookie(session_name(), session_id());
|
||||
if (null !== $originalCookie) {
|
||||
header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false);
|
||||
}
|
||||
}
|
||||
|
||||
$this->loadSession();
|
||||
|
||||
return true;
|
||||
|
|
@ -208,9 +221,16 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
$isRegenerated = session_regenerate_id($destroy);
|
||||
|
||||
// The reference to $_SESSION in session bags is lost in PHP7 and we need to re-create it.
|
||||
// @see https://bugs.php.net/bug.php?id=70013
|
||||
// @see https://bugs.php.net/70013
|
||||
$this->loadSession();
|
||||
|
||||
if (null !== $this->emulateSameSite) {
|
||||
$originalCookie = SessionUtils::popSessionCookie(session_name(), session_id());
|
||||
if (null !== $originalCookie) {
|
||||
header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false);
|
||||
}
|
||||
}
|
||||
|
||||
return $isRegenerated;
|
||||
}
|
||||
|
||||
|
|
@ -219,6 +239,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
*/
|
||||
public function save()
|
||||
{
|
||||
// Store a copy so we can restore the bags in case the session was not left empty
|
||||
$session = $_SESSION;
|
||||
|
||||
foreach ($this->bags as $bag) {
|
||||
|
|
@ -226,32 +247,29 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
unset($_SESSION[$key]);
|
||||
}
|
||||
}
|
||||
if (array($key = $this->metadataBag->getStorageKey()) === array_keys($_SESSION)) {
|
||||
if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) {
|
||||
unset($_SESSION[$key]);
|
||||
}
|
||||
|
||||
// Register custom error handler to catch a possible failure warning during session write
|
||||
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
|
||||
throw new \ErrorException($errstr, $errno, E_WARNING, $errfile, $errline);
|
||||
}, E_WARNING);
|
||||
|
||||
try {
|
||||
$e = null;
|
||||
session_write_close();
|
||||
} catch (\ErrorException $e) {
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
$_SESSION = $session;
|
||||
}
|
||||
if (null !== $e) {
|
||||
// The default PHP error message is not very helpful, as it does not give any information on the current save handler.
|
||||
// Therefore, we catch this error and trigger a warning with a better error message
|
||||
$handler = $this->getSaveHandler();
|
||||
if ($handler instanceof SessionHandlerProxy) {
|
||||
$handler = $handler->getHandler();
|
||||
// Register error handler to add information about the current save handler
|
||||
$previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) {
|
||||
if (E_WARNING === $type && 0 === strpos($msg, 'session_write_close():')) {
|
||||
$handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler;
|
||||
$msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler));
|
||||
}
|
||||
|
||||
trigger_error(sprintf('session_write_close(): Failed to write session data with %s handler', \get_class($handler)), E_USER_WARNING);
|
||||
return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false;
|
||||
});
|
||||
|
||||
try {
|
||||
session_write_close();
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
|
||||
// Restore only if not empty
|
||||
if ($_SESSION) {
|
||||
$_SESSION = $session;
|
||||
}
|
||||
}
|
||||
|
||||
$this->closed = true;
|
||||
|
|
@ -269,7 +287,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
}
|
||||
|
||||
// clear out the session
|
||||
$_SESSION = array();
|
||||
$_SESSION = [];
|
||||
|
||||
// reconnect the bags to the session
|
||||
$this->loadSession();
|
||||
|
|
@ -338,9 +356,9 @@ 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 [key => value]
|
||||
*
|
||||
* @see http://php.net/session.configuration
|
||||
* @see https://php.net/session.configuration
|
||||
*/
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
|
|
@ -348,21 +366,26 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
return;
|
||||
}
|
||||
|
||||
$validOptions = array_flip(array(
|
||||
$validOptions = array_flip([
|
||||
'cache_expire', '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', 'lazy_write', 'name', 'referer_check',
|
||||
'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite',
|
||||
'gc_divisor', 'gc_maxlifetime', 'gc_probability',
|
||||
'lazy_write', 'name', 'referer_check',
|
||||
'serialize_handler', 'use_strict_mode', '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',
|
||||
'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags',
|
||||
));
|
||||
]);
|
||||
|
||||
foreach ($options as $key => $value) {
|
||||
if (isset($validOptions[$key])) {
|
||||
if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) {
|
||||
// PHP < 7.3 does not support same_site cookies. We will emulate it in
|
||||
// the start() method instead.
|
||||
$this->emulateSameSite = $value;
|
||||
continue;
|
||||
}
|
||||
ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value);
|
||||
}
|
||||
}
|
||||
|
|
@ -378,15 +401,13 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
* ini_set('session.save_path', '/tmp');
|
||||
*
|
||||
* or pass in a \SessionHandler instance which configures session.save_handler in the
|
||||
* constructor, for a template see NativeFileSessionHandler or use handlers in
|
||||
* composer package drak/native-session
|
||||
* constructor, for a template see NativeFileSessionHandler.
|
||||
*
|
||||
* @see http://php.net/session-set-save-handler
|
||||
* @see http://php.net/sessionhandlerinterface
|
||||
* @see http://php.net/sessionhandler
|
||||
* @see http://github.com/drak/NativeSession
|
||||
* @see https://php.net/session-set-save-handler
|
||||
* @see https://php.net/sessionhandlerinterface
|
||||
* @see https://php.net/sessionhandler
|
||||
*
|
||||
* @param \SessionHandlerInterface|null $saveHandler
|
||||
* @param AbstractProxy|\SessionHandlerInterface|null $saveHandler
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
|
|
@ -429,11 +450,11 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
$session = &$_SESSION;
|
||||
}
|
||||
|
||||
$bags = array_merge($this->bags, array($this->metadataBag));
|
||||
$bags = array_merge($this->bags, [$this->metadataBag]);
|
||||
|
||||
foreach ($bags as $bag) {
|
||||
$key = $bag->getStorageKey();
|
||||
$session[$key] = isset($session[$key]) ? $session[$key] : array();
|
||||
$session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : [];
|
||||
$bag->initialize($session[$key]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
namespace Symfony\Component\HttpFoundation\Session\Storage;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
|
||||
|
||||
/**
|
||||
* Allows session to be started by PHP and managed by Symfony.
|
||||
*
|
||||
|
|
@ -19,11 +21,14 @@ namespace Symfony\Component\HttpFoundation\Session\Storage;
|
|||
class PhpBridgeSessionStorage extends NativeSessionStorage
|
||||
{
|
||||
/**
|
||||
* @param \SessionHandlerInterface|null $handler
|
||||
* @param MetadataBag $metaBag MetadataBag
|
||||
* @param AbstractProxy|\SessionHandlerInterface|null $handler
|
||||
*/
|
||||
public function __construct($handler = null, MetadataBag $metaBag = null)
|
||||
{
|
||||
if (!\extension_loaded('session')) {
|
||||
throw new \LogicException('PHP extension "session" is required.');
|
||||
}
|
||||
|
||||
$this->setMetadataBag($metaBag);
|
||||
$this->setSaveHandler($handler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ abstract class AbstractProxy
|
|||
/**
|
||||
* Gets the session.save_handler name.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getSaveHandlerName()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,40 +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\Proxy;
|
||||
|
||||
@trigger_error('The '.__NAMESPACE__.'\NativeProxy class is deprecated since Symfony 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* This proxy is built-in session handlers in PHP 5.3.x.
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly.
|
||||
*
|
||||
* @author Drak <drak@zikula.org>
|
||||
*/
|
||||
class NativeProxy extends AbstractProxy
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// this makes an educated guess as to what the handler is since it should already be set.
|
||||
$this->saveHandlerName = ini_get('session.save_handler');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
|
||||
*
|
||||
* @return bool False
|
||||
*/
|
||||
public function isWrapper()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
// \SessionHandlerInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
|
|
@ -44,7 +44,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
|
|
@ -52,7 +52,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return string
|
||||
*/
|
||||
public function read($sessionId)
|
||||
{
|
||||
|
|
@ -60,7 +60,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function write($sessionId, $data)
|
||||
{
|
||||
|
|
@ -68,7 +68,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
|
|
@ -76,7 +76,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
|
|
@ -84,7 +84,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function validateId($sessionId)
|
||||
{
|
||||
|
|
@ -92,7 +92,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @return bool
|
||||
*/
|
||||
public function updateTimestamp($sessionId, $data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ interface SessionStorageInterface
|
|||
* only delete the session data from persistent storage.
|
||||
*
|
||||
* Care: When regenerating the session ID no locking is involved in PHP's
|
||||
* session design. See https://bugs.php.net/bug.php?id=61470 for a discussion.
|
||||
* session design. See https://bugs.php.net/61470 for a discussion.
|
||||
* So you must make sure the regenerated session is saved BEFORE sending the
|
||||
* headers with the new ID. Symfony's HttpKernel offers a listener for this.
|
||||
* See Symfony\Component\HttpKernel\EventListener\SaveSessionListener.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue