Moved database methods into own context class.

This commit is contained in:
flash 2025-02-09 17:39:48 +00:00
parent 21a730d189
commit bac889787a
14 changed files with 94 additions and 62 deletions

View file

@ -1,8 +1,6 @@
<?php
namespace Misuzu;
use Index\Db\DbBackends;
use Index\Config\Db\DbConfig;
use Index\Config\Fs\FsConfig;
define('MSZ_STARTUP', microtime(true));
@ -37,14 +35,4 @@ if($env->hasValues('sentry:dsn'))
});
})($env->scopeTo('sentry'));
$db = DbBackends::create($env->getString('database:dsn', 'null:'));
$db->execute(<<<SQL
SET SESSION time_zone = '+00:00',
sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
SQL);
$cfg = new DbConfig($db, 'msz_config');
Mailer::init($cfg->scopeTo('mail'));
$msz = new MisuzuContext($db, $cfg, $env);
$msz = new MisuzuContext($env);

View file

@ -114,6 +114,8 @@ while($canResetPassword) {
} catch(RuntimeException $ex) {
$tokenInfo = $msz->authCtx->recoveryTokens->createToken($forgotUser, $ipAddress);
$msz->initMailer();
$recoveryMessage = Mailer::template('password-recovery', [
'username' => $forgotUser->name,
'token' => $tokenInfo->code,

View file

@ -153,7 +153,7 @@ if(!empty($_POST)) {
$isEditingTopic = empty($topicInfo) || ($mode === 'edit' && $originalPostInfo->id == $postInfo->id);
if($mode === 'create') {
$postTimeout = $cfg->getInteger('forum.posting.timeout', 5);
$postTimeout = $msz->config->getInteger('forum.posting.timeout', 5);
if($postTimeout > 0) {
$postTimeoutThreshold = new CarbonImmutable(sprintf('-%d seconds', $postTimeout));
$lastPostCreatedAt = $msz->forumCtx->posts->getUserLastPostCreatedAt($currentUser);
@ -173,7 +173,7 @@ if(!empty($_POST)) {
$originalTopicType = $topicInfo?->typeString ?? 'discussion'; // @phpstan-ignore-line: this also
$topicTypeChanged = $topicType !== null && $topicType !== $originalTopicType;
$topicTitleLengths = $cfg->getValues([
$topicTitleLengths = $msz->config->getValues([
['forum.topic.minLength:i', 3],
['forum.topic.maxLength:i', 100],
]);
@ -191,7 +191,7 @@ if(!empty($_POST)) {
}
}
$postTextLengths = $cfg->getValues([
$postTextLengths = $msz->config->getValues([
['forum.post.minLength:i', 1],
['forum.post.maxLength:i', 60000],
]);

View file

@ -81,6 +81,7 @@ if(CSRF::validateRequest() && $canEdit) {
} elseif(!is_string($_POST['send_test_email']) || $_POST['send_test_email'] !== 'yes_send_it') {
$notices[] = 'Invalid request thing shut the fuck up.';
} else {
$msz->initMailer();
$testMail = Mailer::sendMessage(
[$userInfo->emailAddress => $userInfo->name],
'Flashii Test E-mail',

View file

@ -11,7 +11,7 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->loggedIn)
Template::throwError(401);
$dbConn = $msz->dbConn;
$dbConn = $msz->dbCtx->conn;
/** @param string[] $fieldInfos */
function db_to_zip(

46
src/DatabaseContext.php Normal file
View file

@ -0,0 +1,46 @@
<?php
namespace Misuzu;
use Index\Config\Config;
use Index\Db\{DbBackends,DbConnection};
use Index\Db\Migration\{DbMigrationManager,DbMigrationRepo,FsDbMigrationRepo};
use Index\Http\Routing\{HttpMiddleware,RouteHandler,RouteHandlerCommon};
class DatabaseContext implements RouteHandler {
use RouteHandlerCommon;
public private(set) DbConnection $conn;
public function __construct(Config $config) {
$this->conn = DbBackends::create($config->getString('dsn', 'null:'));
$this->conn->execute(<<<SQL
SET SESSION
time_zone = '+00:00',
sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
SQL);
}
public function getQueryCount(): int {
$result = $this->conn->query("SHOW SESSION STATUS LIKE 'Questions'");
return $result->next() ? $result->getInteger(1) : 0;
}
public function createMigrationManager(): DbMigrationManager {
return new DbMigrationManager($this->conn, sprintf('msz_%s', DbMigrationManager::DEFAULT_TABLE));
}
public function createMigrationRepo(): DbMigrationRepo {
return new FsDbMigrationRepo(MSZ_MIGRATIONS);
}
public function getMigrateLockPath(): string {
return sys_get_temp_dir() . '/misuzu-migration-' . hash('sha256', MSZ_ROOT) . '.lock';
}
/** @return void|int */
#[HttpMiddleware('/')]
public function middleware() {
if(is_file($this->getMigrateLockPath()))
return 503;
}
}

View file

@ -3,6 +3,7 @@ namespace Misuzu;
use Index\Dependencies;
use Index\Config\Config;
use Index\Config\Db\DbConfig;
use Index\Db\DbConnection;
use Index\Db\Migration\{DbMigrationManager,DbMigrationRepo,FsDbMigrationRepo};
use Index\Http\HttpRequest;
@ -16,6 +17,7 @@ use RPCii\Server\{HttpRpcServer,RpcServer};
class MisuzuContext {
public private(set) Dependencies $deps;
public private(set) Config $config;
public private(set) TplEnvironment $templating;
public private(set) AuditLog\AuditLogData $auditLog;
@ -26,6 +28,7 @@ class MisuzuContext {
public private(set) News\NewsData $news;
public private(set) Comments\CommentsData $comments;
public private(set) DatabaseContext $dbCtx;
public private(set) Apps\AppsContext $appsCtx;
public private(set) Auth\AuthContext $authCtx;
public private(set) Forum\ForumContext $forumCtx;
@ -43,28 +46,29 @@ class MisuzuContext {
public private(set) UrlRegistry $urls;
public function __construct(
public private(set) DbConnection $dbConn,
public private(set) Config $config,
public private(set) Config $env
) {
$this->deps = new Dependencies;
$this->deps->register($this->deps);
$this->deps->register($this->dbConn);
$this->deps->register($this->config);
$this->deps->register($this->env);
$this->deps->register($this->perms = new Perms\PermissionsData($dbConn));
$this->deps->register($this->dbCtx = new DatabaseContext($this->env->scopeTo('database')));
$this->deps->register($this->dbCtx->conn);
$this->deps->register($this->config = $this->deps->constructLazy(DbConfig::class, tableName: 'msz_config'));
$this->deps->register($this->perms = $this->deps->constructLazy(Perms\PermissionsData::class));
$this->deps->register($this->authInfo = $this->deps->constructLazy(Auth\AuthInfo::class));
$this->deps->register($this->siteInfo = $this->deps->constructLazy(SiteInfo::class, config: $config->scopeTo('site')));
$this->deps->register($this->siteInfo = $this->deps->constructLazy(SiteInfo::class, config: $this->config->scopeTo('site')));
$this->deps->register($this->appsCtx = $this->deps->constructLazy(Apps\AppsContext::class));
$this->deps->register($this->authCtx = $this->deps->constructLazy(Auth\AuthContext::class, config: $config->scopeTo('auth')));
$this->deps->register($this->authCtx = $this->deps->constructLazy(Auth\AuthContext::class, config: $this->config->scopeTo('auth')));
$this->deps->register($this->forumCtx = $this->deps->constructLazy(Forum\ForumContext::class));
$this->deps->register($this->messagesCtx = $this->deps->constructLazy(Messages\MessagesContext::class));
$this->deps->register($this->oauth2Ctx = $this->deps->constructLazy(OAuth2\OAuth2Context::class, config: $config->scopeTo('oauth2')));
$this->deps->register($this->oauth2Ctx = $this->deps->constructLazy(OAuth2\OAuth2Context::class, config: $this->config->scopeTo('oauth2')));
$this->deps->register($this->profileCtx = $this->deps->constructLazy(Profile\ProfileContext::class));
$this->deps->register($this->usersCtx = $this->deps->constructLazy(Users\UsersContext::class));
$this->deps->register($this->redirectsCtx = $this->deps->constructLazy(Redirects\RedirectsContext::class, config: $config->scopeTo('redirects')));
$this->deps->register($this->redirectsCtx = $this->deps->constructLazy(Redirects\RedirectsContext::class, config: $this->config->scopeTo('redirects')));
$this->deps->register($this->auditLog = $this->deps->constructLazy(AuditLog\AuditLogData::class));
$this->deps->register($this->changelog = $this->deps->constructLazy(Changelog\ChangelogData::class));
@ -74,17 +78,8 @@ class MisuzuContext {
$this->deps->register($this->news = $this->deps->constructLazy(News\NewsData::class));
}
public function getDbQueryCount(): int {
$result = $this->dbConn->query('SHOW SESSION STATUS LIKE "Questions"');
return $result->next() ? $result->getInteger(1) : 0;
}
public function createMigrationManager(): DbMigrationManager {
return new DbMigrationManager($this->dbConn, 'msz_' . DbMigrationManager::DEFAULT_TABLE);
}
public function createMigrationRepo(): DbMigrationRepo {
return new FsDbMigrationRepo(MSZ_MIGRATIONS);
public function initMailer(): void {
Mailer::init($this->config->scopeTo('mail'));
}
/** @param mixed[] $params */

View file

@ -38,7 +38,7 @@ final class TemplatingExtension extends AbstractExtension {
new TwigFunction('git_tag', GitInfo::tag(...)),
new TwigFunction('git_branch', GitInfo::branch(...)),
new TwigFunction('startup_time', fn(float $time = MSZ_STARTUP) => microtime(true) - $time),
new TwigFunction('sql_query_count', $this->ctx->getDbQueryCount(...)),
new TwigFunction('sql_query_count', $this->ctx->dbCtx->getQueryCount(...)),
new TwigFunction('msz_header_menu', $this->getHeaderMenu(...)),
new TwigFunction('msz_user_menu', $this->getUserMenu(...)),
new TwigFunction('msz_manage_menu', $this->getManageMenu(...)),

View file

@ -17,15 +17,15 @@ class UserAvatarAsset extends UserImageAsset implements UserAssetScalableInterfa
private const MAX_BYTES = 1000000;
public function getMaxWidth(): int {
global $cfg;
return $cfg->getInteger('avatar.max_res', self::MAX_RES);
global $msz;
return $msz->config->getInteger('avatar.max_res', self::MAX_RES);
}
public function getMaxHeight(): int {
return $this->getMaxWidth();
}
public function getMaxBytes(): int {
global $cfg;
return $cfg->getInteger('avatar.max_size', self::MAX_BYTES);
global $msz;
return $msz->config->getInteger('avatar.max_size', self::MAX_BYTES);
}
public static function clampDimensions(int $dimensions): int {

View file

@ -12,16 +12,16 @@ class UserBackgroundAsset extends UserImageAsset {
private const MAX_BYTES = 1500000;
public function getMaxWidth(): int {
global $cfg;
return $cfg->getInteger('background.max_width', self::MAX_WIDTH);
global $msz;
return $msz->config->getInteger('background.max_width', self::MAX_WIDTH);
}
public function getMaxHeight(): int {
global $cfg;
return $cfg->getInteger('background.max_height', self::MAX_HEIGHT);
global $msz;
return $msz->config->getInteger('background.max_height', self::MAX_HEIGHT);
}
public function getMaxBytes(): int {
global $cfg;
return $cfg->getInteger('background.max_size', self::MAX_BYTES);
global $msz;
return $msz->config->getInteger('background.max_size', self::MAX_BYTES);
}
public function getFileName(): string {

View file

@ -14,8 +14,8 @@ class UserNameHistoryInfo {
public private(set) int $createdTime
) {}
public static function fromResult(DbResult $result): UserPasswordInfo {
return new UserPasswordInfo(
public static function fromResult(DbResult $result): UserNameHistoryInfo {
return new UserNameHistoryInfo(
id: $result->getString(0),
userId: $result->getString(1),
nameBefore: $result->getString(2),

View file

@ -147,7 +147,7 @@ msz_sched_task_func('Resync statistics counters.', true, function() use ($msz) {
];
foreach($stats as $name => $query) {
$result = $msz->dbConn->query($query);
$result = $msz->dbCtx->conn->query($query);
$msz->counters->set($name, $result->next() ? $result->getInteger(0) : 0);
}
});
@ -166,7 +166,7 @@ msz_sched_task_func('Omega disliking comments...', true, function() use ($msz) {
if(!is_array($commentIds))
return;
$stmt = $msz->dbConn->prepare('REPLACE INTO msz_comments_votes (comment_id, user_id, comment_vote) SELECT ?, user_id, -1 FROM msz_users');
$stmt = $msz->dbCtx->conn->prepare('REPLACE INTO msz_comments_votes (comment_id, user_id, comment_vote) SELECT ?, user_id, -1 FROM msz_users');
foreach($commentIds as $commentId) {
$stmt->addParameter(1, $commentId);
$stmt->execute();
@ -178,9 +178,9 @@ msz_sched_task_func('Announcing random topics...', true, function() use ($msz) {
if(!is_array($categoryIds))
return;
$stmtRevert = $msz->dbConn->prepare('UPDATE msz_forum_topics SET topic_type = 0 WHERE forum_id = ? AND topic_type = 2');
$stmtRandom = $msz->dbConn->prepare('SELECT topic_id FROM msz_forum_topics WHERE forum_id = ? AND topic_deleted IS NULL ORDER BY RAND() LIMIT 1');
$stmtAnnounce = $msz->dbConn->prepare('UPDATE msz_forum_topics SET topic_type = 2 WHERE topic_id = ?');
$stmtRevert = $msz->dbCtx->conn->prepare('UPDATE msz_forum_topics SET topic_type = 0 WHERE forum_id = ? AND topic_type = 2');
$stmtRandom = $msz->dbCtx->conn->prepare('SELECT topic_id FROM msz_forum_topics WHERE forum_id = ? AND topic_deleted IS NULL ORDER BY RAND() LIMIT 1');
$stmtAnnounce = $msz->dbCtx->conn->prepare('UPDATE msz_forum_topics SET topic_type = 2 WHERE topic_id = ?');
foreach($categoryIds as $categoryId) {
$stmtRevert->addParameter(1, $categoryId);
$stmtRevert->execute();
@ -201,8 +201,8 @@ msz_sched_task_func('Changing category icons...', false, function() use ($msz) {
if(!is_array($categoryIds))
return;
$stmtIcon = $msz->dbConn->prepare('UPDATE msz_forum_categories SET forum_icon = COALESCE(?, forum_icon), forum_name = COALESCE(?, forum_name), forum_colour = ((ROUND(RAND() * 255) << 16) | (ROUND(RAND() * 255) << 8) | ROUND(RAND() * 255)) WHERE forum_id = ?');
$stmtUnlock = $msz->dbConn->prepare('UPDATE msz_forum_topics SET topic_locked = IF(?, NULL, COALESCE(topic_locked, NOW())) WHERE topic_id = ?');
$stmtIcon = $msz->dbCtx->conn->prepare('UPDATE msz_forum_categories SET forum_icon = COALESCE(?, forum_icon), forum_name = COALESCE(?, forum_name), forum_colour = ((ROUND(RAND() * 255) << 16) | (ROUND(RAND() * 255) << 8) | ROUND(RAND() * 255)) WHERE forum_id = ?');
$stmtUnlock = $msz->dbCtx->conn->prepare('UPDATE msz_forum_topics SET topic_locked = IF(?, NULL, COALESCE(topic_locked, NOW())) WHERE topic_id = ?');
foreach($categoryIds as $categoryId) {
$scoped = $msz->config->scopeTo(sprintf('forum.rngicon.fc%d', $categoryId));
@ -247,7 +247,7 @@ foreach($schedTasks as $task) {
try {
switch($task->type) {
case 'sql':
$affected = $msz->dbConn->execute($task->command);
$affected = $msz->dbCtx->conn->execute($task->command);
echo $affected . ' rows affected. ' . PHP_EOL;
break;

View file

@ -9,13 +9,13 @@ try {
chmod(MSZ_ROOT . '/.migrating', 0777);
echo 'Creating migration manager...' . PHP_EOL;
$manager = $msz->createMigrationManager();
$manager = $msz->dbCtx->createMigrationManager();
echo 'Preparing to run migrations...' . PHP_EOL;
$manager->init();
echo 'Creating migration repository...' . PHP_EOL;
$repo = $msz->createMigrationRepo();
$repo = $msz->dbCtx->createMigrationRepo();
echo 'Running migrations...' . PHP_EOL;
$completed = $manager->processMigrations($repo);

View file

@ -4,14 +4,14 @@ use Index\Db\Migration\FsDbMigrationRepo;
require_once __DIR__ . '/../misuzu.php';
$repo = $msz->createMigrationRepo();
$repo = $msz->dbCtx->createMigrationRepo();
if(!($repo instanceof FsDbMigrationRepo)) {
echo 'Migration repository type does not support creation of templates.' . PHP_EOL;
return;
}
$baseName = implode(' ', array_slice($argv, 1));
$manager = $msz->createMigrationManager();
$manager = $msz->dbCtx->createMigrationManager();
try {
$names = $manager->createNames($baseName);