rosavox/lib/alveolata/session/implementation-memory.php
2025-05-23 07:33:29 +00:00

255 lines
4.8 KiB
PHP

<?php
namespace alveolata\session;
// require_once(DIR_ALVEOLATA . '/definitions.php');
/**
* @author Christian Fraß <frass@greenscale.de>
*/
class struct_subject_memory {
/**
* @var string
* @author Christian Fraß <frass@greenscale.de>
*/
public $id;
/**
* @var integar
* @author Christian Fraß <frass@greenscale.de>
*/
public $timestamp;
/**
* @var map<string,string>
* @author Christian Fraß <frass@greenscale.de>
*/
public $data;
/**
* @author Christian Fraß <frass@greenscale.de>
*/
public function __construct(
string $id,
int $timestamp = -1,
array $data = []
)
{
if ($timestamp < 0) $timestamp = time();
$this->id = $id;
$this->timestamp = $timestamp;
$this->data = $data;
}
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
class _state_memory {
/**
* @var map<string,struct_subject_memory>
* @author Christian Fraß <frass@greenscale.de>
*/
public static $pool = [];
/**
* @var int
* @author Christian Fraß <frass@greenscale.de>
*/
public static $time_to_live_in_seconds = 3600; // ~1h
}
/**
* @throw \Exception if timed out
* @author Christian Fraß <frass@greenscale.de>
*/
function _memory_ttlcheck(
struct_subject_memory $subject
) : void
{
$now = time();
if (($subject->timestamp + _state_memory::$time_to_live_in_seconds) < $now) {
throw (new \Exception('session timed out'));
}
}
/**
* @param struct_subject_memory $subject
* @param string $key
* @throw \Exception if no such key
* @author Christian Fraß <frass@greenscale.de>
*/
function _memory_keycheck(
struct_subject_memory $subject,
string $key
) : void
{
if (! array_key_exists($key, $subject->data)) {
$message = sprintf('no key "%s"', $key);
throw (new \Exception($message));
}
}
/**
* @param struct_subject_memory $subject
* @author Christian Fraß <frass@greenscale.de>
*/
function _memory_update(
struct_subject_memory $subject
) : void
{
$subject->timestamp = time();
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
function memory_begin(
) : struct_subject_memory
{
$id = hash('sha256', strval(time()));
$subject = (new struct_subject_memory($id));
_state_memory::$pool[$id] = $subject;
return $subject;
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
function memory_get(
string $id
) : struct_subject_memory
{
if (! array_key_exists($id, _state_memory::$pool)) {
$message = sprintf('no session "%s"', $id);
throw (new \Exception($message));
}
else {
$subject = _state_memory::$pool[$id];
_memory_ttlcheck($subject);
return $subject;
}
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
function memory_id(
struct_subject_memory $subject
) : string
{
return $subject->id;
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
function memory_read(
struct_subject_memory $subject,
string $key
) : string
{
_memory_ttlcheck($subject);
_memory_keycheck($subject, $key);
$value = $subject->data[$key];
_memory_update($subject);
return $value;
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
function memory_write(
struct_subject_memory $subject,
string $key,
string $value
) : void
{
_memory_ttlcheck($subject);
$subject->data[$key] = $value;
_memory_update($subject);
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
function memory_remove(
struct_subject_memory $subject,
string $key
) : void
{
_memory_ttlcheck($subject);
_memory_keycheck($subject, $key);
unset($subject->data[$key]);
_memory_update($subject);
}
/**
* @author Christian Fraß <frass@greenscale.de>
* @todo check for existence and ttl
*/
function memory_end(
struct_subject_memory $subject
) : void
{
$subject->id = 0;
$subject->timestamp = 0;
$subject->data = [];
unset(_state_memory::$pool[$subject->id]);
}
/**
* @author Christian Fraß <frass@greenscale.de>
*/
class implementation_memory implements interface_session {
/**
* @var struct_subject_memory
* @author Christian Fraß <frass@greenscale.de>
*/
private $subject;
/**
* @author Christian Fraß <frass@greenscale.de>
*/
private function __construct(struct_subject_memory $subject) {$this->subject = $subject;}
/**
* implementations
*
* @author Christian Fraß <frass@greenscale.de>
*/
public static function begin() : interface_session {return (new implementation_memory(memory_begin()));}
public static function get(string $id) : interface_session {return (new implementation_memory(memory_get($id)));}
public function id() : string {return memory_id($this->subject);}
public function read(string $key) : string {return memory_read($this->subject, $key);}
public function write(string $key, string $value) : void {memory_write($this->subject, $key, $value);}
public function remove(string $key) : void {memory_remove($this->subject, $key);}
public function end() : void {memory_end($this->subject);}
}
?>