diff --git a/composer.json b/composer.json index d9ce25fe..03e1c717 100644 --- a/composer.json +++ b/composer.json @@ -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" diff --git a/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php b/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php index 03c832e3..76f46e69 100644 --- a/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php +++ b/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php @@ -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 diff --git a/src/Ratchet/Session/Storage/Proxy/VirtualProxyForSymfony7.php b/src/Ratchet/Session/Storage/Proxy/VirtualProxyForSymfony7.php new file mode 100644 index 00000000..6c2a7756 --- /dev/null +++ b/src/Ratchet/Session/Storage/Proxy/VirtualProxyForSymfony7.php @@ -0,0 +1,60 @@ +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"); + } +} diff --git a/src/Ratchet/Session/Storage/VirtualSessionStorage.php b/src/Ratchet/Session/Storage/VirtualSessionStorage.php index c56c5f87..8b940312 100644 --- a/src/Ratchet/Session/Storage/VirtualSessionStorage.php +++ b/src/Ratchet/Session/Storage/VirtualSessionStorage.php @@ -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 diff --git a/src/Ratchet/Session/Storage/VirtualSessionStorageForSymfony7.php b/src/Ratchet/Session/Storage/VirtualSessionStorageForSymfony7.php new file mode 100644 index 00000000..911bdb35 --- /dev/null +++ b/src/Ratchet/Session/Storage/VirtualSessionStorageForSymfony7.php @@ -0,0 +1,96 @@ +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; + } +}