255 lines
4.8 KiB
PHP
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);}
|
|
|
|
}
|
|
|
|
?>
|