2023-04-07 19:32:15 +02:00
|
|
|
<?php namespace SokoWeb\Session;
|
|
|
|
|
|
|
|
use DateTime;
|
|
|
|
use SokoWeb\Database\Query\Modify;
|
|
|
|
use SokoWeb\Database\Query\Select;
|
2023-04-19 22:19:40 +02:00
|
|
|
use SokoWeb\Interfaces\Database\IConnection;
|
2023-04-07 19:32:15 +02:00
|
|
|
use SokoWeb\Interfaces\Database\IResultSet;
|
|
|
|
use SokoWeb\Interfaces\Session\ISessionHandler;
|
|
|
|
|
|
|
|
class DatabaseSessionHandler implements ISessionHandler
|
|
|
|
{
|
2023-04-19 22:19:40 +02:00
|
|
|
private IConnection $dbConnection;
|
|
|
|
|
2023-05-02 10:52:22 +02:00
|
|
|
private string $table;
|
|
|
|
|
2023-05-02 12:21:05 +02:00
|
|
|
private DateTime $shouldBeNewerThan;
|
|
|
|
|
2023-04-07 19:32:15 +02:00
|
|
|
private bool $exists = false;
|
|
|
|
|
|
|
|
private bool $written = false;
|
|
|
|
|
2023-05-02 12:21:05 +02:00
|
|
|
public function __construct(IConnection $dbConnection, string $table, DateTime $shouldBeNewerThan)
|
2023-04-19 22:19:40 +02:00
|
|
|
{
|
|
|
|
$this->dbConnection = $dbConnection;
|
2023-05-02 10:52:22 +02:00
|
|
|
$this->table = $table;
|
2023-05-02 12:21:05 +02:00
|
|
|
$this->shouldBeNewerThan = $shouldBeNewerThan;
|
2023-04-19 22:19:40 +02:00
|
|
|
}
|
|
|
|
|
2023-04-07 19:32:15 +02:00
|
|
|
public function open($savePath, $sessionName): bool
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function close(): bool
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function read($id): string
|
|
|
|
{
|
2023-05-02 10:52:22 +02:00
|
|
|
$select = new Select($this->dbConnection, $this->table);
|
2023-05-02 12:21:05 +02:00
|
|
|
$select->columns(['data', 'updated']);
|
2023-04-07 19:32:15 +02:00
|
|
|
$select->whereId(substr($id, 0, 32));
|
|
|
|
|
|
|
|
$result = $select->execute()->fetch(IResultSet::FETCH_ASSOC);
|
|
|
|
if ($result === null) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->exists = true;
|
|
|
|
|
2023-05-02 12:21:05 +02:00
|
|
|
if (new DateTime($result['updated']) < $this->shouldBeNewerThan) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
2023-04-07 19:32:15 +02:00
|
|
|
return $result['data'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function write($id, $data): bool
|
|
|
|
{
|
2023-05-02 10:52:22 +02:00
|
|
|
$modify = new Modify($this->dbConnection, $this->table);
|
2023-04-07 19:32:15 +02:00
|
|
|
|
|
|
|
if ($this->exists) {
|
|
|
|
$modify->setId(substr($id, 0, 32));
|
|
|
|
} else {
|
|
|
|
$modify->setExternalId(substr($id, 0, 32));
|
|
|
|
}
|
|
|
|
|
|
|
|
$modify->set('data', $data);
|
|
|
|
$modify->set('updated', (new DateTime())->format('Y-m-d H:i:s'));
|
|
|
|
$modify->save();
|
|
|
|
|
|
|
|
$this->written = true;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function destroy($id): bool
|
|
|
|
{
|
2023-05-02 10:52:22 +02:00
|
|
|
$modify = new Modify($this->dbConnection, $this->table);
|
2023-04-07 19:32:15 +02:00
|
|
|
$modify->setId(substr($id, 0, 32));
|
|
|
|
$modify->delete();
|
|
|
|
|
|
|
|
$this->exists = false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function gc($maxlifetime): bool
|
|
|
|
{
|
|
|
|
// empty on purpose
|
|
|
|
// old sessions are deleted by MaintainDatabaseCommand
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function create_sid(): string
|
|
|
|
{
|
|
|
|
return bin2hex(random_bytes(16));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function validateId($id): bool
|
|
|
|
{
|
|
|
|
return preg_match('/^[a-f0-9]{32}$/', $id) === 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function updateTimestamp($id, $data): bool
|
|
|
|
{
|
|
|
|
if ($this->written) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-05-02 10:52:22 +02:00
|
|
|
$modify = new Modify($this->dbConnection, $this->table);
|
2023-04-07 19:32:15 +02:00
|
|
|
|
|
|
|
$modify->setId(substr($id, 0, 32));
|
|
|
|
$modify->set('updated', (new DateTime())->format('Y-m-d H:i:s'));
|
|
|
|
$modify->save();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|