chore(install): Fix formatting

ой
This commit is contained in:
celestora 2025-02-22 20:51:43 +02:00
parent 22bae8a2e1
commit 0b010d8c56
4 changed files with 157 additions and 113 deletions

View file

@ -24,8 +24,9 @@ class FetchToncoinTransactions extends Command
public function __construct() public function __construct()
{ {
$ctx = DatabaseConnection::i()->getContext(); $ctx = DatabaseConnection::i()->getContext();
if (in_array("cryptotransactions", $ctx->getStructure()->getTables())) if (in_array("cryptotransactions", $ctx->getStructure()->getTables())) {
$this->transactions = $ctx->table("cryptotransactions"); $this->transactions = $ctx->table("cryptotransactions");
}
parent::__construct(); parent::__construct();
} }

View file

@ -21,8 +21,9 @@ class RebuildImagesCommand extends Command
public function __construct() public function __construct()
{ {
$ctx = DatabaseConnection::i()->getContext(); $ctx = DatabaseConnection::i()->getContext();
if (in_array("photos", $ctx->getStructure()->getTables())) if (in_array("photos", $ctx->getStructure()->getTables())) {
$this->images = $ctx->table("photos"); $this->images = $ctx->table("photos");
}
parent::__construct(); parent::__construct();
} }

View file

@ -14,12 +14,13 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
class UpgradeCommand extends Command { class UpgradeCommand extends Command
{
protected static $defaultName = "upgrade"; protected static $defaultName = "upgrade";
private Connection $db; private Connection $db;
private Connection $eventDb; private Connection $eventDb;
private array $chandlerTables = [ private array $chandlerTables = [
"CHANDLERACLPERMISSIONALIASES", "CHANDLERACLPERMISSIONALIASES",
"CHANDLERACLGROUPSPERMISSIONS", "CHANDLERACLGROUPSPERMISSIONS",
@ -27,288 +28,328 @@ class UpgradeCommand extends Command {
"CHANDLERACLRELATIONS", "CHANDLERACLRELATIONS",
"CHANDLERGROUPS", "CHANDLERGROUPS",
"CHANDLERTOKENS", "CHANDLERTOKENS",
"CHANDLERUSERS" "CHANDLERUSERS",
]; ];
public function __construct() public function __construct()
{ {
$this->db = DatabaseConnection::i()->getConnection(); $this->db = DatabaseConnection::i()->getConnection();
$this->eventDb = eventdb()->getConnection(); $this->eventDb = eventdb()->getConnection();
parent::__construct(); parent::__construct();
} }
protected function configure(): void protected function configure(): void
{ {
$this->setDescription("Upgrade OpenVK installation") $this->setDescription("Upgrade OpenVK installation")
->setHelp("This command upgrades database schema after OpenVK was updated") ->setHelp("This command upgrades database schema after OpenVK was updated")
->addOption("quick", "Q", InputOption::VALUE_NEGATABLE, ->addOption(
"Don't display warning before migrating database", false) "quick",
->addOption("repair", "R", InputOption::VALUE_NEGATABLE, "Q",
"Attempt to repair database schema if tables are missing", false) InputOption::VALUE_NEGATABLE,
->addOption("oneshot", "O", InputOption::VALUE_NONE, "Don't display warning before migrating database",
"Only execute one operation") false
->addArgument("chandler", InputArgument::OPTIONAL, )
"Location of Chandler installation"); ->addOption(
"repair",
"R",
InputOption::VALUE_NEGATABLE,
"Attempt to repair database schema if tables are missing",
false
)
->addOption(
"oneshot",
"O",
InputOption::VALUE_NONE,
"Only execute one operation"
)
->addArgument(
"chandler",
InputArgument::OPTIONAL,
"Location of Chandler installation"
);
} }
protected function checkDatabaseReadiness(bool &$chandlerOk, bool &$ovkOk, bool &$eventOk, bool &$migrationsOk): void protected function checkDatabaseReadiness(bool &$chandlerOk, bool &$ovkOk, bool &$eventOk, bool &$migrationsOk): void
{ {
$tables = $this->db->query("SHOW TABLES")->fetchAll(); $tables = $this->db->query("SHOW TABLES")->fetchAll();
$tables = array_map(fn ($x) => strtoupper($x->offsetGet(0)), $tables); $tables = array_map(fn($x) => strtoupper($x->offsetGet(0)), $tables);
$missingTables = array_diff($this->chandlerTables, $tables); $missingTables = array_diff($this->chandlerTables, $tables);
if (sizeof($missingTables) == 0) if (sizeof($missingTables) == 0) {
$chandlerOk = true; $chandlerOk = true;
else if (sizeof($missingTables) == sizeof($this->chandlerTables)) } elseif (sizeof($missingTables) == sizeof($this->chandlerTables)) {
$chandlerOk = null; $chandlerOk = null;
else } else {
$chandlerOk = false; $chandlerOk = false;
}
if (is_null($this->eventDb)) { if (is_null($this->eventDb)) {
$eventOk = false; $eventOk = false;
} else if (is_null($this->eventDb->query("SHOW TABLES LIKE \"notifications\"")->fetch())) { } elseif (is_null($this->eventDb->query("SHOW TABLES LIKE \"notifications\"")->fetch())) {
$eventOk = null; $eventOk = null;
} else { } else {
$eventOk = true; $eventOk = true;
} }
$ovkOk = in_array("PROFILES", $tables); $ovkOk = in_array("PROFILES", $tables);
$migrationsOk = in_array("OVK_UPGRADE_HISTORY", $tables); $migrationsOk = in_array("OVK_UPGRADE_HISTORY", $tables);
} }
protected function executeSqlScript(int $errCode, string $script, SymfonyStyle $io, bool $transaction = false, protected function executeSqlScript(
bool $eventDb = false): int int $errCode,
{ string $script,
SymfonyStyle $io,
bool $transaction = false,
bool $eventDb = false
): int {
$pdo = ($eventDb ? $this->eventDb : $this->db)->getPdo(); $pdo = ($eventDb ? $this->eventDb : $this->db)->getPdo();
$res = false; $res = false;
try { try {
if ($transaction) if ($transaction) {
$res = $pdo->beginTransaction(); $res = $pdo->beginTransaction();
}
$res = $pdo->exec($script); $res = $pdo->exec($script);
if ($transaction) if ($transaction) {
$res = $pdo->commit(); $res = $pdo->commit();
} catch (\PDOException $e) {} }
} catch (\PDOException $e) {
if ($res === false) }
if ($res === false) {
goto error; goto error;
}
return 0; return 0;
error: error:
$io->getErrorStyle()->error([ $io->getErrorStyle()->error([
"Failed to execute SQL statement:", "Failed to execute SQL statement:",
implode("\t", $pdo->errorInfo()) implode("\t", $pdo->errorInfo()),
]); ]);
return $errCode; return $errCode;
} }
protected function getNextLevel(bool $eventDb = false): int protected function getNextLevel(bool $eventDb = false): int
{ {
$tbl = $eventDb ? "ovk_events_upgrade_history" : "ovk_upgrade_history"; $tbl = $eventDb ? "ovk_events_upgrade_history" : "ovk_upgrade_history";
$record = $this->db->query("SELECT level FROM $tbl ORDER BY level DESC LIMIT 1"); $record = $this->db->query("SELECT level FROM $tbl ORDER BY level DESC LIMIT 1");
if (!$record->getRowCount()) if (!$record->getRowCount()) {
return 0; return 0;
}
return $record->fetchField() + 1; return $record->fetchField() + 1;
} }
protected function getMigrationFiles(bool $eventDb = false): array protected function getMigrationFiles(bool $eventDb = false): array
{ {
$files = []; $files = [];
$root = dirname(__DIR__ . "/../install/init-static-db.sql"); $root = dirname(__DIR__ . "/../install/init-static-db.sql");
$dir = $eventDb ? "sqls/eventdb" : "sqls"; $dir = $eventDb ? "sqls/eventdb" : "sqls";
foreach (glob("$root/$dir/*.sql") as $file) foreach (glob("$root/$dir/*.sql") as $file) {
$files[(int) basename($file)] = basename($file); $files[(int) basename($file)] = basename($file);
}
ksort($files); ksort($files);
return $files; return $files;
} }
protected function installChandler(InputInterface $input, SymfonyStyle $io, bool $drop = false): int protected function installChandler(InputInterface $input, SymfonyStyle $io, bool $drop = false): int
{ {
$chandlerLocation = $input->getArgument("chandler") ?? (__DIR__ . "/../../../../"); $chandlerLocation = $input->getArgument("chandler") ?? (__DIR__ . "/../../../../");
$chandlerConfigLocation = "$chandlerLocation/chandler.yml"; $chandlerConfigLocation = "$chandlerLocation/chandler.yml";
if (!file_exists($chandlerConfigLocation)) { if (!file_exists($chandlerConfigLocation)) {
$err = ["Could not find chandler location. Perhaps your config is too unique?"]; $err = ["Could not find chandler location. Perhaps your config is too unique?"];
if (!$input->getOption("chandler")) if (!$input->getOption("chandler")) {
$err[] = "Specify absolute path to your chandler installation using the --chandler option."; $err[] = "Specify absolute path to your chandler installation using the --chandler option.";
}
$io->getErrorStyle()->error($err); $io->getErrorStyle()->error($err);
return 21; return 21;
} }
if ($drop) { if ($drop) {
$bar = new ProgressBar($io, sizeof($this->chandlerTables)); $bar = new ProgressBar($io, sizeof($this->chandlerTables));
$io->writeln("Dropping chandler tables..."); $io->writeln("Dropping chandler tables...");
foreach ($bar->iterate($this->chandlerTables) as $table) foreach ($bar->iterate($this->chandlerTables) as $table) {
$this->db->query("DROP TABLE IF EXISTS $table;"); $this->db->query("DROP TABLE IF EXISTS $table;");
}
$io->newLine(); $io->newLine();
} }
$installFile = file_get_contents("$chandlerLocation/install/init-db.sql"); $installFile = file_get_contents("$chandlerLocation/install/init-db.sql");
return $this->executeSqlScript(22, $installFile, $io); return $this->executeSqlScript(22, $installFile, $io);
} }
protected function initSchema(SymfonyStyle $io): int protected function initSchema(SymfonyStyle $io): int
{ {
$installFile = file_get_contents(__DIR__ . "/../install/init-static-db.sql"); $installFile = file_get_contents(__DIR__ . "/../install/init-static-db.sql");
return $this->executeSqlScript(31, $installFile, $io); return $this->executeSqlScript(31, $installFile, $io);
} }
protected function initEventSchema(SymfonyStyle $io): int protected function initEventSchema(SymfonyStyle $io): int
{ {
$installFile = file_get_contents(__DIR__ . "/../install/init-event-db.sql"); $installFile = file_get_contents(__DIR__ . "/../install/init-event-db.sql");
return $this->executeSqlScript(31, $installFile, $io, true, true); return $this->executeSqlScript(31, $installFile, $io, true, true);
} }
protected function initUpgradeLog(SymfonyStyle $io): int protected function initUpgradeLog(SymfonyStyle $io): int
{ {
$installFile = file_get_contents(__DIR__ . "/../install/init-migration-table.sql"); $installFile = file_get_contents(__DIR__ . "/../install/init-migration-table.sql");
return $this->executeSqlScript(31, $installFile, $io, true); return $this->executeSqlScript(31, $installFile, $io, true);
} }
protected function runMigrations(SymfonyStyle $io, bool $eventDb, bool $oneshot): int protected function runMigrations(SymfonyStyle $io, bool $eventDb, bool $oneshot): int
{ {
$dir = $eventDb ? "sqls/eventdb" : "sqls"; $dir = $eventDb ? "sqls/eventdb" : "sqls";
$tbl = $eventDb ? "ovk_events_upgrade_history" : "ovk_upgrade_history"; $tbl = $eventDb ? "ovk_events_upgrade_history" : "ovk_upgrade_history";
$nextLevel = $this->getNextLevel($eventDb); $nextLevel = $this->getNextLevel($eventDb);
$migrations = array_filter($this->getMigrationFiles($eventDb), fn ($id) => $id >= $nextLevel, $migrations = array_filter(
ARRAY_FILTER_USE_KEY); $this->getMigrationFiles($eventDb),
fn($id) => $id >= $nextLevel,
if (!sizeof($migrations)) ARRAY_FILTER_USE_KEY
);
if (!sizeof($migrations)) {
return 24; return 24;
}
$uname = addslashes(`whoami`); $uname = addslashes(`whoami`);
$bar = new ProgressBar($io, sizeof($migrations)); $bar = new ProgressBar($io, sizeof($migrations));
$bar->setFormat("very_verbose"); $bar->setFormat("very_verbose");
foreach ($bar->iterate($migrations) as $num => $migration) { foreach ($bar->iterate($migrations) as $num => $migration) {
$script = file_get_contents(__DIR__ . "/../install/$dir/$migration"); $script = file_get_contents(__DIR__ . "/../install/$dir/$migration");
$res = $this->executeSqlScript(100 + $num, $script, $io, true, $eventDb); $res = $this->executeSqlScript(100 + $num, $script, $io, true, $eventDb);
if ($res != 0) { if ($res != 0) {
$io->getErrorStyle()->error("Error while executing migration №$num"); $io->getErrorStyle()->error("Error while executing migration №$num");
return $res; return $res;
} }
$t = time(); $t = time();
$this->db->query("INSERT INTO $tbl VALUES ($num, $t, \"$uname\");"); $this->db->query("INSERT INTO $tbl VALUES ($num, $t, \"$uname\");");
if ($oneshot) if ($oneshot) {
return 5; return 5;
}
} }
$io->newLine(); $io->newLine();
return 0; return 0;
} }
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$oneShotMode = $input->getOption("oneshot"); $oneShotMode = $input->getOption("oneshot");
$io = new SymfonyStyle($input, $output); $io = new SymfonyStyle($input, $output);
if (!$input->getOption("quick")) { if (!$input->getOption("quick")) {
$io->writeln("Do full backup of the database before executing this command!"); $io->writeln("Do full backup of the database before executing this command!");
$io->writeln("Command will resume execution after 5 seconds."); $io->writeln("Command will resume execution after 5 seconds.");
$io->writeln("You can skip this warning with --quick option."); $io->writeln("You can skip this warning with --quick option.");
sleep(5); sleep(5);
} }
$migrationsOk = false; $migrationsOk = false;
$chandlerOk = false; $chandlerOk = false;
$eventOk = false; $eventOk = false;
$ovkOk = false; $ovkOk = false;
$this->checkDatabaseReadiness($chandlerOk, $ovkOk, $eventOk, $migrationsOk); $this->checkDatabaseReadiness($chandlerOk, $ovkOk, $eventOk, $migrationsOk);
$res = -1; $res = -1;
if ($chandlerOk === null) { if ($chandlerOk === null) {
$io->writeln("Chandler schema not detected, attempting to install..."); $io->writeln("Chandler schema not detected, attempting to install...");
$res = $this->installChandler($input, $io); $res = $this->installChandler($input, $io);
} else if ($chandlerOk === false) { } elseif ($chandlerOk === false) {
if ($input->getOption("repair")) { if ($input->getOption("repair")) {
$io->warning("Chandler schema detected but is broken, attempting to repair..."); $io->warning("Chandler schema detected but is broken, attempting to repair...");
$res = $this->installChandler($input, $io, true); $res = $this->installChandler($input, $io, true);
} else { } else {
$io->writeln("Chandler schema detected but is broken"); $io->writeln("Chandler schema detected but is broken");
$io->writeln("Run command with --repair to repair (PERMISSIONS WILL BE LOST)"); $io->writeln("Run command with --repair to repair (PERMISSIONS WILL BE LOST)");
return 1; return 1;
} }
} }
if ($res > 0) if ($res > 0) {
return $res; return $res;
else if ($res == 0 && $oneShotMode) } elseif ($res == 0 && $oneShotMode) {
return 5; return 5;
}
if (!$ovkOk) { if (!$ovkOk) {
$io->writeln("Initializing OpenVK schema..."); $io->writeln("Initializing OpenVK schema...");
$res = $this->initSchema($io); $res = $this->initSchema($io);
if ($res > 0) if ($res > 0) {
return $res; return $res;
else if ($oneShotMode) } elseif ($oneShotMode) {
return 5; return 5;
}
} }
if (!$migrationsOk) { if (!$migrationsOk) {
$io->writeln("Initializing upgrade log..."); $io->writeln("Initializing upgrade log...");
$res = $this->initUpgradeLog($io); $res = $this->initUpgradeLog($io);
if ($res > 0) if ($res > 0) {
return $res; return $res;
else if ($oneShotMode) } elseif ($oneShotMode) {
return 5; return 5;
}
} }
if ($eventOk !== false) { if ($eventOk !== false) {
if ($eventOk === null) { if ($eventOk === null) {
$io->writeln("Initializing event database..."); $io->writeln("Initializing event database...");
$res = $this->initEventSchema($io); $res = $this->initEventSchema($io);
if ($res > 0) if ($res > 0) {
return $res; return $res;
else if ($oneShotMode) } elseif ($oneShotMode) {
return 5; return 5;
}
} }
$io->writeln("Upgrading event database..."); $io->writeln("Upgrading event database...");
$res = $this->runMigrations($io, true, $oneShotMode); $res = $this->runMigrations($io, true, $oneShotMode);
if ($res == 24) if ($res == 24) {
$output->writeln("Event database already up to date."); $output->writeln("Event database already up to date.");
else if ($res > 0) } elseif ($res > 0) {
return $res; return $res;
}
} }
$io->writeln("Upgrading database..."); $io->writeln("Upgrading database...");
$res = $this->runMigrations($io, false, $oneShotMode); $res = $this->runMigrations($io, false, $oneShotMode);
if (!$res) { if (!$res) {
$io->success("Database has been upgraded!"); $io->success("Database has been upgraded!");
return 0; return 0;
} else if ($res != 24) { } elseif ($res != 24) {
return $res; return $res;
} }
$io->writeln("Database up to date. Nothing left to do."); $io->writeln("Database up to date. Nothing left to do.");
return 0; return 0;
} }
} }

View file

@ -443,9 +443,10 @@ function downloadable_name(string $text): string
} }
return (function () { return (function () {
if (php_sapi_name() != "cli") if (php_sapi_name() != "cli") {
_ovk_check_environment(); _ovk_check_environment();
}
require __DIR__ . "/vendor/autoload.php"; require __DIR__ . "/vendor/autoload.php";
setlocale(LC_TIME, "POSIX"); setlocale(LC_TIME, "POSIX");