diff --git a/system/Session/Handlers/RedisHandler.php b/system/Session/Handlers/RedisHandler.php index 27390174fb50..213272bb87c7 100644 --- a/system/Session/Handlers/RedisHandler.php +++ b/system/Session/Handlers/RedisHandler.php @@ -142,17 +142,19 @@ protected function setSavePath(): void } } - $password = $query['auth'] ?? null; - $database = isset($query['database']) ? (int) $query['database'] : 0; - $timeout = isset($query['timeout']) ? (float) $query['timeout'] : 0.0; - $prefix = $query['prefix'] ?? null; + $persistent = isset($query['persistent']) ? filter_var($query['persistent'], FILTER_VALIDATE_BOOL) : null; + $password = $query['auth'] ?? null; + $database = isset($query['database']) ? (int) $query['database'] : 0; + $timeout = isset($query['timeout']) ? (float) $query['timeout'] : 0.0; + $prefix = $query['prefix'] ?? null; $this->savePath = [ - 'host' => $host, - 'port' => $port, - 'password' => $password, - 'database' => $database, - 'timeout' => $timeout, + 'host' => $host, + 'port' => $port, + 'password' => $password, + 'database' => $database, + 'timeout' => $timeout, + 'persistent' => $persistent, ]; if ($prefix !== null) { @@ -176,13 +178,11 @@ public function open($path, $name): bool $redis = new Redis(); - if ( - ! $redis->connect( - $this->savePath['host'], - $this->savePath['port'], - $this->savePath['timeout'], - ) - ) { + $funcConnection = isset($this->savePath['persistent']) && $this->savePath['persistent'] === true + ? 'pconnect' + : 'connect'; + + if ($redis->{$funcConnection}($this->savePath['host'], $this->savePath['port'], $this->savePath['timeout']) === false) { $this->logger->error('Session: Unable to connect to Redis with the configured settings.'); } elseif (isset($this->savePath['password']) && ! $redis->auth($this->savePath['password'])) { $this->logger->error('Session: Unable to authenticate to Redis instance.'); diff --git a/tests/system/Session/Handlers/Database/RedisHandlerTest.php b/tests/system/Session/Handlers/Database/RedisHandlerTest.php index 7e38a81e97de..9244385a908e 100644 --- a/tests/system/Session/Handlers/Database/RedisHandlerTest.php +++ b/tests/system/Session/Handlers/Database/RedisHandlerTest.php @@ -163,81 +163,133 @@ public static function provideSetSavePath(): iterable 'w/o protocol' => [ '127.0.0.1:6379', [ - 'host' => 'tcp://127.0.0.1', - 'port' => 6379, - 'password' => null, - 'database' => 0, - 'timeout' => 0.0, + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => null, + 'database' => 0, + 'timeout' => 0.0, + 'persistent' => null, ], ], 'tls auth' => [ 'tls://127.0.0.1:6379?auth=password', [ - 'host' => 'tls://127.0.0.1', - 'port' => 6379, - 'password' => 'password', - 'database' => 0, - 'timeout' => 0.0, + 'host' => 'tls://127.0.0.1', + 'port' => 6379, + 'password' => 'password', + 'database' => 0, + 'timeout' => 0.0, + 'persistent' => null, ], ], 'tcp auth' => [ 'tcp://127.0.0.1:6379?auth=password', [ - 'host' => 'tcp://127.0.0.1', - 'port' => 6379, - 'password' => 'password', - 'database' => 0, - 'timeout' => 0.0, + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => 'password', + 'database' => 0, + 'timeout' => 0.0, + 'persistent' => null, ], ], 'timeout float' => [ 'tcp://127.0.0.1:6379?timeout=2.5', [ - 'host' => 'tcp://127.0.0.1', - 'port' => 6379, - 'password' => null, - 'database' => 0, - 'timeout' => 2.5, + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => null, + 'database' => 0, + 'timeout' => 2.5, + 'persistent' => null, ], ], 'timeout int' => [ 'tcp://127.0.0.1:6379?timeout=10', [ - 'host' => 'tcp://127.0.0.1', - 'port' => 6379, - 'password' => null, - 'database' => 0, - 'timeout' => 10.0, + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => null, + 'database' => 0, + 'timeout' => 10.0, + 'persistent' => null, ], ], 'auth acl' => [ 'tcp://localhost:6379?auth[user]=redis-admin&auth[pass]=admin-password', [ - 'host' => 'tcp://localhost', - 'port' => 6379, - 'password' => ['user' => 'redis-admin', 'pass' => 'admin-password'], - 'database' => 0, - 'timeout' => 0.0, + 'host' => 'tcp://localhost', + 'port' => 6379, + 'password' => ['user' => 'redis-admin', 'pass' => 'admin-password'], + 'database' => 0, + 'timeout' => 0.0, + 'persistent' => null, ], ], 'unix domain socket' => [ 'unix:///tmp/redis.sock', [ - 'host' => '/tmp/redis.sock', - 'port' => 0, - 'password' => null, - 'database' => 0, - 'timeout' => 0.0, + 'host' => '/tmp/redis.sock', + 'port' => 0, + 'password' => null, + 'database' => 0, + 'timeout' => 0.0, + 'persistent' => null, ], ], 'unix domain socket w/o protocol' => [ '/tmp/redis.sock', [ - 'host' => '/tmp/redis.sock', - 'port' => 0, - 'password' => null, - 'database' => 0, - 'timeout' => 0.0, + 'host' => '/tmp/redis.sock', + 'port' => 0, + 'password' => null, + 'database' => 0, + 'timeout' => 0.0, + 'persistent' => null, + ], + ], + 'persistent connection with numeric one' => [ + 'tcp://127.0.0.1:6379?timeout=10&persistent=1', + [ + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => null, + 'database' => 0, + 'timeout' => 10.0, + 'persistent' => true, + ], + ], + 'no persistent connection with numeric zero' => [ + 'tcp://127.0.0.1:6379?timeout=10&persistent=0', + [ + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => null, + 'database' => 0, + 'timeout' => 10.0, + 'persistent' => false, + ], + ], + 'persistent connection with boolean true' => [ + 'tcp://127.0.0.1:6379?timeout=10&persistent=true', + [ + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => null, + 'database' => 0, + 'timeout' => 10.0, + 'persistent' => true, + ], + ], + 'persistent connection with boolean false' => [ + 'tcp://127.0.0.1:6379?timeout=10&persistent=false', + [ + 'host' => 'tcp://127.0.0.1', + 'port' => 6379, + 'password' => null, + 'database' => 0, + 'timeout' => 10.0, + 'persistent' => false, ], ], ]; diff --git a/user_guide_src/source/changelogs/v4.7.0.rst b/user_guide_src/source/changelogs/v4.7.0.rst index e8124847efc2..4d2cb01afd92 100644 --- a/user_guide_src/source/changelogs/v4.7.0.rst +++ b/user_guide_src/source/changelogs/v4.7.0.rst @@ -269,6 +269,7 @@ Libraries - **Image:** The ``ImageMagickHandler`` has been rewritten to rely solely on the PHP ``imagick`` extension. - **Image:** Added ``ImageMagickHandler::clearMetadata()`` method to remove image metadata for privacy protection. - **ResponseTrait:** Added ``paginate``` method to simplify paginated API responses. See :ref:`ResponseTrait::paginate() ` for details. +- **Session:** Added ``persistent`` config item to redis handler. - **Time:** added methods ``Time::addCalendarMonths()`` and ``Time::subCalendarMonths()`` - **Time:** Added ``Time::isPast()`` and ``Time::isFuture()`` convenience methods. See :ref:`isPast ` and :ref:`isFuture ` for details. - **View:** Added the ability to override namespaced views (e.g., from modules/packages) by placing a matching file structure within the **app/Views/overrides** directory. See :ref:`Overriding Namespaced Views ` for details.