The TryingToScale PHP framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

134 lines
3.6 KiB

<?php
declare(strict_types=1);
/**
* @author Robert Strutts <Robert@TryingToScale.com>
* @copyright Copyright (c) 2022, Robert Strutts.
* @license https://mit-license.org/
*/
namespace tts\services\sessions;
class redis_sessions implements \SessionHandlerInterface {
public static int $zlib_compression_level = 4;
public static bool $use_compression = true;
public $ttl = 1800; // 30 minutes default
protected $db;
protected $prefix;
private $enc;
public function __construct($enc, array $options) {
$exists = \main_tts\registry::get('di')->exists('session_redis_servers');
if ($exists) {
$db = \main_tts\registry::get('di')->get_service('session_redis_servers');
}
if (! is_object($db)) {
throw new \Exception("Session service type not set");
}
$this->db = $options['db'] ?? $db;
if (isset($options['prefix'])) {
$prefix = $options['prefix'];
} else {
$prefix = 'SESS:';
}
$this->prefix = $prefix;
$this->enc = $enc;
if (isset($options['compression_level'])) {
self::$zlib_compression_level = $options['compression_level'];
}
if (isset($options['use_compression'])) {
self::$use_compression = $options['use_compression'];
}
}
private function encrypt(string & $data): void {
if ($this->enc === false) {
return;
}
$data = $this->enc->encrypt($data);
}
private function decrypt(string & $data): void {
if ($this->enc === false) {
return;
}
try {
$data = $this->enc->decrypt($data);
} catch (\Exception $e) {
$data = false; // Maybe it has no data to decode
}
}
private function compress(string & $data): void {
if (self::$use_compression === false) {
return;
}
$data = gzdeflate($data, self::$zlib_compression_level);
if ($data === false) {
throw new \Exception('Failed to compress session data');
}
}
private function decompress(string & $data): void {
if (self::$use_compression === false) {
return;
}
$ret = gzinflate($data);
if ($ret !== false) {
$data = $ret;
}
}
public function open($save_path, $session_name): bool{
// No action necessary because connection is injected
// in constructor and arguments are not applicable.
}
public function close(): bool {
$this->db = null;
unset($this->db);
}
public function read($id): false|string {
$id = $this->prefix . $id;
$data = $this->db->get($id);
$this->db->expire($id, $this->ttl);
if ($data === null) {
return "";
}
$data = base64_decode($data);
if ($data === false) {
return "";
}
$this->decrypt($data);
if ($data === false) {
return "";
}
$this->decompress($data);
return ($data !== false) ? $data : '';
}
public function write($id, $data): bool {
$this->compress($data);
$this->encrypt($data);
$data = base64_encode($data);
$id = $this->prefix . $id;
$this->db->set($id, $data);
$this->db->expire($id, $this->ttl);
}
public function destroy($id): bool {
$this->db->del($this->prefix . $id);
}
public function gc($max_lifetime): int|false {
// no action necessary because using EXPIRE
}
}