Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
, "react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5"
, "react/event-loop": ">=0.4"
, "guzzlehttp/psr7": "^1.7|^2.0"
, "symfony/http-foundation": "^2.6|^3.0|^4.0|^5.0|^6.0"
, "symfony/routing": "^2.6|^3.0|^4.0|^5.0|^6.0"
, "symfony/http-foundation": "^2.6|^3.0|^4.0|^5.0|^6.0|^7.0"
, "symfony/routing": "^2.6|^3.0|^4.0|^5.0|^6.0|^7.0"
}
, "require-dev": {
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
Expand Down
7 changes: 5 additions & 2 deletions src/Ratchet/Session/Storage/Proxy/VirtualProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
namespace Ratchet\Session\Storage\Proxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;

if (PHP_VERSION_ID > 80000 && (new \ReflectionMethod('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy','getId'))->hasReturnType()) {
// alias to class for Symfony 6 on PHP 8+ that uses native types like `getId(): string`
if (PHP_VERSION_ID > 80200 && (new \ReflectionMethod('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy','setId'))->hasReturnType()) {
// alias to class for Symfony 7 on PHP 8.2+ using native types like `setId(string $id): void`
class_alias(__NAMESPACE__ . '\\VirtualProxyForSymfony7', __NAMESPACE__ . '\\VirtualProxy');
} elseif (PHP_VERSION_ID > 80000 && (new \ReflectionMethod('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy','getId'))->hasReturnType()) {
// alias to class for Symfony 6 on PHP 8+ using native types like `getId(): string`
class_alias(__NAMESPACE__ . '\\VirtualProxyForSymfony6', __NAMESPACE__ . '\\VirtualProxy');
} else {
// fall back to class without native types
Expand Down
60 changes: 60 additions & 0 deletions src/Ratchet/Session/Storage/Proxy/VirtualProxyForSymfony7.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
namespace Ratchet\Session\Storage\Proxy;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;

/**
* [internal] VirtualProxy for Symfony 7 on PHP 8.2+ using native types like `setId(string $id): void`
*
* @internal used internally only, should not be referenced directly
* @see VirtualProxy
*/
class VirtualProxyForSymfony7 extends SessionHandlerProxy {
/**
* @var string
*/
protected $_sessionId;

/**
* @var string
*/
protected $_sessionName;

/**
* {@inheritdoc}
*/
public function __construct(\SessionHandlerInterface $handler) {
parent::__construct($handler);

$this->saveHandlerName = 'user';
$this->_sessionName = ini_get('session.name');
}

/**
* {@inheritdoc}
*/
public function getId(): string {
return $this->_sessionId;
}

/**
* {@inheritdoc}
*/
public function setId(string $id): void {
$this->_sessionId = $id;
}

/**
* {@inheritdoc}
*/
public function getName(): string {
return $this->_sessionName;
}

/**
* DO NOT CALL THIS METHOD
* @internal
*/
public function setName(string $name): void {
throw new \RuntimeException("Can not change session name in VirtualProxy");
}
}
7 changes: 5 additions & 2 deletions src/Ratchet/Session/Storage/VirtualSessionStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
use Ratchet\Session\Storage\Proxy\VirtualProxy;
use Ratchet\Session\Serialize\HandlerInterface;

if (PHP_VERSION_ID > 80000 && (new \ReflectionMethod('Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage','start'))->hasReturnType()) {
// alias to class for Symfony 6 on PHP 8+ that uses native types like `start(): bool`
if (PHP_VERSION_ID > 80200 && (new \ReflectionMethod('Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage','save'))->hasReturnType()) {
// alias to class for Symfony 7 on PHP 8.2+ using native types like `save(): void`
class_alias(__NAMESPACE__ . '\\VirtualSessionStorageForSymfony7', __NAMESPACE__ . '\\VirtualSessionStorage');
} elseif (PHP_VERSION_ID > 80000 && (new \ReflectionMethod('Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage','start'))->hasReturnType()) {
// alias to class for Symfony 6 on PHP 8+ using native types like `start(): bool`
class_alias(__NAMESPACE__ . '\\VirtualSessionStorageForSymfony6', __NAMESPACE__ . '\\VirtualSessionStorage');
} else {
// fall back to class without native types
Expand Down
96 changes: 96 additions & 0 deletions src/Ratchet/Session/Storage/VirtualSessionStorageForSymfony7.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
namespace Ratchet\Session\Storage;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
use Ratchet\Session\Storage\Proxy\VirtualProxy;
use Ratchet\Session\Serialize\HandlerInterface;

/**
* [internal] VirtualSessionStorage for Symfony 7 on PHP 8.2+ using native types like `save(): void`
*
* @internal used internally only, should not be referenced directly
* @see VirtualSessionStorage
*/
class VirtualSessionStorageForSymfony7 extends NativeSessionStorage {
/**
* @var \Ratchet\Session\Serialize\HandlerInterface
*/
protected $_serializer;

/**
* @param \SessionHandlerInterface $handler
* @param string $sessionId The ID of the session to retrieve
* @param \Ratchet\Session\Serialize\HandlerInterface $serializer
*/
public function __construct(\SessionHandlerInterface $handler, $sessionId, HandlerInterface $serializer) {
$this->setSaveHandler($handler);
$this->saveHandler->setId($sessionId);
$this->_serializer = $serializer;
$this->setMetadataBag(null);
}

/**
* {@inheritdoc}
*/
public function start(): bool {
if ($this->started && !$this->closed) {
return true;
}

// You have to call Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::open() to use
// pdo_sqlite (and possible pdo_*) as session storage, if you are using a DSN string instead of a \PDO object
// in the constructor. The method arguments are filled with the values, which are also used by the symfony
// framework in this case. This must not be the best choice, but it works.
$this->saveHandler->open(session_save_path(), session_name());

$rawData = $this->saveHandler->read($this->saveHandler->getId());
$sessionData = $this->_serializer->unserialize($rawData);

$this->loadSession($sessionData);

if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
$this->saveHandler->setActive(false);
}

return true;
}

/**
* {@inheritdoc}
*/
public function regenerate(bool $destroy = false, ?int $lifetime = null): bool {
// .. ?
return false;
}

/**
* {@inheritdoc}
*/
public function save(): void {
// get the data from the bags?
// serialize the data
// save the data using the saveHandler
// $this->saveHandler->write($this->saveHandler->getId(),

if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) {
$this->saveHandler->setActive(false);
}

$this->closed = true;
}

/**
* {@inheritdoc}
*/
public function setSaveHandler(AbstractProxy|\SessionHandlerInterface|null $saveHandler): void {
if (!($saveHandler instanceof \SessionHandlerInterface)) {
throw new \InvalidArgumentException('Handler must be instance of SessionHandlerInterface');
}

if (!($saveHandler instanceof VirtualProxy)) {
$saveHandler = new VirtualProxy($saveHandler);
}

$this->saveHandler = $saveHandler;
}
}