diff --git a/phpstan-baseline.neon.dist b/phpstan-baseline.neon.dist index 986601771fef..4f83a4ea0c80 100644 --- a/phpstan-baseline.neon.dist +++ b/phpstan-baseline.neon.dist @@ -295,11 +295,6 @@ parameters: count: 1 path: system/Session/Handlers/RedisHandler.php - - - message: "#^Property CodeIgniter\\\\Session\\\\Session\\:\\:\\$sessionExpiration \\(int\\) in isset\\(\\) is not nullable\\.$#" - count: 1 - path: system/Session/Session.php - - message: "#^Negated boolean expression is always false\\.$#" count: 1 diff --git a/system/Session/Session.php b/system/Session/Session.php index 70afefce27ca..7d353c92a196 100644 --- a/system/Session/Session.php +++ b/system/Session/Session.php @@ -43,6 +43,8 @@ class Session implements SessionInterface * The storage driver to use: files, database, redis, memcached * * @var string + * + * @deprecated Use $this->config->driver. */ protected $sessionDriverName; @@ -50,6 +52,8 @@ class Session implements SessionInterface * The session cookie name, must contain only [0-9a-z_-] characters. * * @var string + * + * @deprecated Use $this->config->cookieName. */ protected $sessionCookieName = 'ci_session'; @@ -58,11 +62,13 @@ class Session implements SessionInterface * Setting it to 0 (zero) means expire when the browser is closed. * * @var int + * + * @deprecated Use $this->config->expiration. */ protected $sessionExpiration = 7200; /** - * The location to save sessions to, driver dependent.. + * The location to save sessions to, driver dependent. * * For the 'files' driver, it's a path to a writable directory. * WARNING: Only absolute paths are supported! @@ -74,6 +80,8 @@ class Session implements SessionInterface * IMPORTANT: You are REQUIRED to set a valid save path! * * @var string + * + * @deprecated Use $this->config->savePath. */ protected $sessionSavePath; @@ -84,6 +92,8 @@ class Session implements SessionInterface * your session table's PRIMARY KEY when changing this setting. * * @var bool + * + * @deprecated Use $this->config->matchIP. */ protected $sessionMatchIP = false; @@ -91,6 +101,8 @@ class Session implements SessionInterface * How many seconds between CI regenerating the session ID. * * @var int + * + * @deprecated Use $this->config->timeToUpdate. */ protected $sessionTimeToUpdate = 300; @@ -100,6 +112,8 @@ class Session implements SessionInterface * will be later deleted by the garbage collector. * * @var bool + * + * @deprecated Use $this->config->regenerateDestroy. */ protected $sessionRegenerateDestroy = false; @@ -156,6 +170,11 @@ class Session implements SessionInterface */ protected $sidRegexp; + /** + * Session Config + */ + protected SessionConfig $config; + /** * Constructor. * @@ -165,14 +184,16 @@ public function __construct(SessionHandlerInterface $driver, SessionConfig $sess { $this->driver = $driver; + $this->config = $session; + // Store Session configurations $this->sessionDriverName = $session->driver; - $this->sessionCookieName = $session->cookieName ?? $this->sessionCookieName; - $this->sessionExpiration = $session->expiration ?? $this->sessionExpiration; + $this->sessionCookieName = $session->cookieName; + $this->sessionExpiration = $session->expiration; $this->sessionSavePath = $session->savePath; - $this->sessionMatchIP = $session->matchIP ?? $this->sessionMatchIP; - $this->sessionTimeToUpdate = $session->timeToUpdate ?? $this->sessionTimeToUpdate; - $this->sessionRegenerateDestroy = $session->regenerateDestroy ?? $this->sessionRegenerateDestroy; + $this->sessionMatchIP = $session->matchIP; + $this->sessionTimeToUpdate = $session->timeToUpdate; + $this->sessionRegenerateDestroy = $session->regenerateDestroy; /** @var App $config */ $config = config('App'); @@ -186,8 +207,8 @@ public function __construct(SessionHandlerInterface $driver, SessionConfig $sess /** @var CookieConfig|null $cookie */ $cookie = config('Cookie'); - $this->cookie = (new Cookie($this->sessionCookieName, '', [ - 'expires' => $this->sessionExpiration === 0 ? 0 : Time::now()->getTimestamp() + $this->sessionExpiration, + $this->cookie = (new Cookie($this->config->cookieName, '', [ + 'expires' => $this->config->expiration === 0 ? 0 : Time::now()->getTimestamp() + $this->config->expiration, 'path' => $cookie->path ?? $config->cookiePath, 'domain' => $cookie->domain ?? $config->cookieDomain, 'secure' => $cookie->secure ?? $config->cookieSecure, @@ -230,32 +251,32 @@ public function start() $this->setSaveHandler(); // Sanitize the cookie, because apparently PHP doesn't do that for userspace handlers - if (isset($_COOKIE[$this->sessionCookieName]) - && (! is_string($_COOKIE[$this->sessionCookieName]) || ! preg_match('#\A' . $this->sidRegexp . '\z#', $_COOKIE[$this->sessionCookieName])) + if (isset($_COOKIE[$this->config->cookieName]) + && (! is_string($_COOKIE[$this->config->cookieName]) || ! preg_match('#\A' . $this->sidRegexp . '\z#', $_COOKIE[$this->config->cookieName])) ) { - unset($_COOKIE[$this->sessionCookieName]); + unset($_COOKIE[$this->config->cookieName]); } $this->startSession(); // Is session ID auto-regeneration configured? (ignoring ajax requests) if ((empty($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest') - && ($regenerateTime = $this->sessionTimeToUpdate) > 0 + && ($regenerateTime = $this->config->timeToUpdate) > 0 ) { if (! isset($_SESSION['__ci_last_regenerate'])) { $_SESSION['__ci_last_regenerate'] = Time::now()->getTimestamp(); } elseif ($_SESSION['__ci_last_regenerate'] < (Time::now()->getTimestamp() - $regenerateTime)) { - $this->regenerate((bool) $this->sessionRegenerateDestroy); + $this->regenerate((bool) $this->config->regenerateDestroy); } } // Another work-around ... PHP doesn't seem to send the session cookie // unless it is being currently created or regenerated - elseif (isset($_COOKIE[$this->sessionCookieName]) && $_COOKIE[$this->sessionCookieName] === session_id()) { + elseif (isset($_COOKIE[$this->config->cookieName]) && $_COOKIE[$this->config->cookieName] === session_id()) { $this->setCookie(); } $this->initVars(); - $this->logger->info("Session: Class initialized using '" . $this->sessionDriverName . "' driver."); + $this->logger->info("Session: Class initialized using '" . $this->config->driver . "' driver."); return $this; } @@ -270,7 +291,7 @@ public function start() public function stop() { setcookie( - $this->sessionCookieName, + $this->config->cookieName, session_id(), ['expires' => 1, 'path' => $this->cookie->getPath(), 'domain' => $this->cookie->getDomain(), 'secure' => $this->cookie->isSecure(), 'httponly' => true] ); @@ -285,16 +306,12 @@ public function stop() */ protected function configure() { - if (empty($this->sessionCookieName)) { - $this->sessionCookieName = ini_get('session.name'); - } else { - ini_set('session.name', $this->sessionCookieName); - } + ini_set('session.name', $this->config->cookieName); $sameSite = $this->cookie->getSameSite() ?: ucfirst(Cookie::SAMESITE_LAX); $params = [ - 'lifetime' => $this->sessionExpiration, + 'lifetime' => $this->config->expiration, 'path' => $this->cookie->getPath(), 'domain' => $this->cookie->getDomain(), 'secure' => $this->cookie->isSecure(), @@ -305,14 +322,12 @@ protected function configure() ini_set('session.cookie_samesite', $sameSite); session_set_cookie_params($params); - if (! isset($this->sessionExpiration)) { - $this->sessionExpiration = (int) ini_get('session.gc_maxlifetime'); - } elseif ($this->sessionExpiration > 0) { - ini_set('session.gc_maxlifetime', (string) $this->sessionExpiration); + if ($this->config->expiration > 0) { + ini_set('session.gc_maxlifetime', (string) $this->config->expiration); } - if (! empty($this->sessionSavePath)) { - ini_set('session.save_path', $this->sessionSavePath); + if (! empty($this->config->savePath)) { + ini_set('session.save_path', $this->config->savePath); } // Security is king @@ -419,12 +434,12 @@ private function removeOldSessionCookie(): void $response = Services::response(); $cookieStoreInResponse = $response->getCookieStore(); - if (! $cookieStoreInResponse->has($this->sessionCookieName)) { + if (! $cookieStoreInResponse->has($this->config->cookieName)) { return; } // CookieStore is immutable. - $newCookieStore = $cookieStoreInResponse->remove($this->sessionCookieName); + $newCookieStore = $cookieStoreInResponse->remove($this->config->cookieName); // But clear() method clears cookies in the object (not immutable). $cookieStoreInResponse->clear(); @@ -924,7 +939,7 @@ protected function startSession() */ protected function setCookie() { - $expiration = $this->sessionExpiration === 0 ? 0 : Time::now()->getTimestamp() + $this->sessionExpiration; + $expiration = $this->config->expiration === 0 ? 0 : Time::now()->getTimestamp() + $this->config->expiration; $this->cookie = $this->cookie->withValue(session_id())->withExpires($expiration); $response = Services::response(); diff --git a/system/Test/Mock/MockSession.php b/system/Test/Mock/MockSession.php index f5290f26525d..9f558e1034ad 100644 --- a/system/Test/Mock/MockSession.php +++ b/system/Test/Mock/MockSession.php @@ -57,7 +57,7 @@ protected function startSession() */ protected function setCookie() { - $expiration = $this->sessionExpiration === 0 ? 0 : Time::now()->getTimestamp() + $this->sessionExpiration; + $expiration = $this->config->expiration === 0 ? 0 : Time::now()->getTimestamp() + $this->config->expiration; $this->cookie = $this->cookie->withValue(session_id())->withExpires($expiration); $this->cookies[] = $this->cookie;