implement separated models

This commit is contained in:
yggverse 2024-08-02 22:00:28 +03:00
parent 47b7344e2e
commit 10534df069
17 changed files with 662 additions and 520 deletions

View file

@ -4,13 +4,20 @@ declare(strict_types=1);
namespace Yggverse\Yoda\Model;
use \PDO;
use \Pdo;
class Database
{
private PDO $_connection;
// Dependencies
public Pdo $connection;
private bool $_exists;
// Requirements
public Database\Auth $auth;
public Database\Bookmark $bookmark;
public Database\Cache $cache;
public Database\History $history;
public Database\Identity $identity;
public Database\Session $session;
public function __construct(
string $filename,
@ -18,12 +25,12 @@ class Database
?string $password = null
) {
// Status
$this->_exists = file_exists(
$exists = file_exists(
$filename
);
// Init database connection
$this->_connection = new PDO(
// Init dependencies
$this->connection = new Pdo(
sprintf(
'sqlite:%s',
$filename
@ -32,519 +39,48 @@ class Database
$password
);
$this->_connection->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
$this->connection->setAttribute(
Pdo::ATTR_ERRMODE,
Pdo::ERRMODE_EXCEPTION
);
$this->_connection->setAttribute(
PDO::ATTR_DEFAULT_FETCH_MODE,
PDO::FETCH_OBJ
$this->connection->setAttribute(
Pdo::ATTR_DEFAULT_FETCH_MODE,
Pdo::FETCH_OBJ
);
// Init tables
$this->_connection->query('
CREATE TABLE IF NOT EXISTS `auth`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`active` INTEGER NOT NULL,
`identity` INTEGER NOT NULL,
`request` VARCHAR(1024) NOT NULL
)
');
// Init requirements
$this->auth = new Database\Auth(
$this->connection
);
$this->_connection->query('
CREATE TABLE IF NOT EXISTS `bookmark`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`request` VARCHAR(1024) UNIQUE,
`title` VARCHAR(255)
)
');
$this->bookmark = new Database\Bookmark(
$this->connection
);
$this->_connection->query('
CREATE TABLE IF NOT EXISTS `cache`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`request` VARCHAR(1024) UNIQUE,
`mime` VARCHAR(255),
`title` VARCHAR(255),
`subtitle` VARCHAR(255),
`tooltip` VARCHAR(255),
`data` BLOB
);
');
$this->cache = new Database\Cache(
$this->connection
);
$this->_connection->query('
CREATE TABLE IF NOT EXISTS `history`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`url` VARCHAR(1024) NOT NULL,
`title` VARCHAR(255)
)
');
$this->history = new Database\History(
$this->connection
);
$this->_connection->query('
CREATE TABLE IF NOT EXISTS `identity`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`active` INTEGER NOT NULL,
`name` VARCHAR(255),
`crt` TEXT NOT NULL,
`key` TEXT NOT NULL
)
');
$this->identity = new Database\Identity(
$this->connection
);
$this->_connection->query('
CREATE TABLE IF NOT EXISTS `session`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`time` INTEGER NOT NULL,
`request` VARCHAR(1024)
);
');
$this->session = new Database\Session(
$this->connection
);
// Initial setup
if (!$this->_exists)
// Init data
if (!$exists)
{
// Add gemini protocol homepage
$this->addSession(
'gemini://geminiprotocol.net/'
);
// Add yggverse homepage
$this->addSession(
// Open yggverse homepage
$this->session->add(
'gemini://yggverse.cities.yesterweb.org/'
);
}
}
// Bookmark
public function addBookmark(
?string $request = null,
?string $title = null,
?int $time = null
): int
{
$query = $this->_connection->prepare(
'INSERT INTO `bookmark` (
`time`,
`request`,
`title`
) VALUES (
:time,
:request,
:title
)'
);
$query->execute(
[
':time' => $time ? $time : time(),
':request' => $request,
':title' => $title
]
);
return intval(
$this->_connection->lastInsertId()
);
}
public function getBookmark(
?string $request = null
): ?object
{
$query = $this->_connection->prepare(
'SELECT * FROM `bookmark` WHERE `request` LIKE :request'
);
$query->execute(
[
':request' => $request
]
);
if ($record = $query->fetch())
{
return $record;
}
return null;
}
public function findBookmark(
?string $value = null,
int $start = 0,
int $limit = 1000
): array
{
$query = $this->_connection->prepare(
sprintf(
'SELECT * FROM `bookmark`
WHERE `request` LIKE :value OR `title` LIKE :value
ORDER BY `id` DESC
LIMIT %d,%d',
$start,
$limit
)
);
$query->execute(
[
':value' => sprintf(
'%%%s%%',
strval(
$value
)
)
]
);
return $query->fetchAll();
}
public function deleteBookmark(
int $id
): int
{
$query = $this->_connection->query(
sprintf(
'DELETE FROM `bookmark` WHERE `id` = %d',
$id
)
);
return $query->rowCount();
}
public function toggleBookmark(
?string $request = null,
?string $title = null,
?int $time = null
): bool
{
if ($record = $this->getBookmark($request))
{
$this->deleteBookmark(
$record->id
);
return false;
}
else
{
$this->addBookmark(
$request,
$title,
$time
);
return true;
}
}
// Cache
public function addCache(
?string $request = null,
?string $mime = null,
?string $title = null,
?string $subtitle = null,
?string $tooltip = null,
?string $data = null,
?int $time = null
): int
{
$query = $this->_connection->prepare(
'INSERT INTO `cache` (
`time`,
`request`,
`mime`,
`title`,
`subtitle`,
`tooltip`,
`data`
) VALUES (
:time,
:request,
:mime,
:title,
:subtitle,
:tooltip,
:data
)'
);
$query->execute(
[
':time' => $time ? $time : time(),
':request' => $request,
':mime' => $mime,
':title' => $title,
':subtitle' => $subtitle,
':tooltip' => $tooltip,
':data' => $data
]
);
return intval(
$this->_connection->lastInsertId()
);
}
public function getCache(
string $request = ''
): ?object
{
$query = $this->_connection->prepare(
'SELECT * FROM `cache` WHERE `request` LIKE :request'
);
$query->execute(
[
':request' => $request
]
);
if ($cache = $query->fetch())
{
return $cache;
}
return null;
}
public function deleteCache(
int $id
): int
{
$query = $this->_connection->query(
sprintf(
'DELETE FROM `cache` WHERE `id` = %d',
$id
)
);
return $query->rowCount();
}
public function cleanCache(
int $timeout = 0
): int
{
$query = $this->_connection->query(
sprintf(
'DELETE FROM `cache` WHERE `time` + %d < %d',
$timeout,
time()
)
);
return $query->rowCount();
}
public function renewCache(
string $request,
?string $mime = null,
?string $title = null,
?string $subtitle = null,
?string $tooltip = null,
?string $data = null,
?int $time = null
): void
{
// Find same records match URL
$query = $this->_connection->prepare(
'SELECT * FROM `cache` WHERE `request` LIKE :request'
);
$query->execute(
[
':request' => $request
]
);
// Drop previous records
foreach ($query->fetchAll() as $record)
{
$this->deleteCache(
$record->id
);
}
// Add new record
$this->addCache(
$request,
$mime,
$title,
$subtitle,
$tooltip,
$data,
$time
);
}
// History
public function addHistory(
string $url,
?string $title = null
): int
{
$query = $this->_connection->prepare(
'INSERT INTO `history` (`time`, `url`, `title`) VALUES (:time, :url, :title)'
);
$query->execute(
[
':time' => time(),
':url' => $url,
':title' => $title
]
);
return intval(
$this->_connection->lastInsertId()
);
}
public function findHistory(
string $value = '',
int $start = 0,
int $limit = 1000
): array
{
$query = $this->_connection->prepare(
sprintf(
'SELECT * FROM `history`
WHERE `url` LIKE :value OR `title` LIKE :value
ORDER BY `id` DESC
LIMIT %d,%d',
$start,
$limit
)
);
$query->execute(
[
':value' => sprintf(
'%%%s%%',
$value
)
]
);
return $query->fetchAll();
}
public function deleteHistory(
int $id
): int
{
$query = $this->_connection->query(
sprintf(
'DELETE FROM `history` WHERE `id` = %d',
$id
)
);
return $query->rowCount();
}
public function cleanHistory(
int $timeout = 0
): int
{
$query = $this->_connection->query(
sprintf(
'DELETE FROM `history` WHERE `time` + %d < %d',
$timeout,
time()
)
);
return $query->rowCount();
}
public function renewHistory(
string $url,
?string $title = null
): void
{
// Find same records match URL
$query = $this->_connection->prepare(
'SELECT * FROM `history` WHERE `url` LIKE :url'
);
$query->execute(
[
':url' => $url
]
);
// Drop previous records
foreach ($query->fetchAll() as $record)
{
$this->deleteHistory(
$record->id
);
}
// Add new record
$this->addHistory(
$url,
$title
);
}
// Session
public function addSession(
?string $request = null,
?int $time = null
): int
{
$query = $this->_connection->prepare(
'INSERT INTO `session` (`time`, `request`) VALUES (:time, :request)'
);
$query->execute(
[
':time' => $time ? $time : time(),
':request' => $request
]
);
return intval(
$this->_connection->lastInsertId()
);
}
public function getSession(): array
{
$query = $this->_connection->query(
'SELECT * FROM `session`'
);
if ($session = $query->fetchAll())
{
return $session;
}
return [];
}
public function cleanSession(): int
{
$query = $this->_connection->query(
'DELETE FROM `session`'
);
return $query->rowCount();
}
}