mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-04-01 00:55:28 +00:00
550 lines
No EOL
12 KiB
PHP
550 lines
No EOL
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Yggverse\Yoda\Model;
|
|
|
|
use \PDO;
|
|
|
|
class Database
|
|
{
|
|
private PDO $_connection;
|
|
|
|
private bool $_exists;
|
|
|
|
public function __construct(
|
|
string $filename,
|
|
?string $username = null,
|
|
?string $password = null
|
|
) {
|
|
// Status
|
|
$this->_exists = file_exists(
|
|
$filename
|
|
);
|
|
|
|
// Init database connection
|
|
$this->_connection = new PDO(
|
|
sprintf(
|
|
'sqlite:%s',
|
|
$filename
|
|
),
|
|
$username,
|
|
$password
|
|
);
|
|
|
|
$this->_connection->setAttribute(
|
|
PDO::ATTR_ERRMODE,
|
|
PDO::ERRMODE_EXCEPTION
|
|
);
|
|
|
|
$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
|
|
)
|
|
');
|
|
|
|
$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->_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->_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->_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->_connection->query('
|
|
CREATE TABLE IF NOT EXISTS `session`
|
|
(
|
|
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
`time` INTEGER NOT NULL,
|
|
`request` VARCHAR(1024)
|
|
);
|
|
');
|
|
|
|
// Initial setup
|
|
if (!$this->_exists)
|
|
{
|
|
// Add gemini protocol homepage
|
|
$this->addSession(
|
|
'gemini://geminiprotocol.net/'
|
|
);
|
|
|
|
// Add yggverse homepage
|
|
$this->addSession(
|
|
'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();
|
|
}
|
|
} |