web-base/cli.php

329 lines
8.4 KiB
PHP
Raw Normal View History

2021-04-06 16:34:12 +02:00
<?php
include_once 'core/core.php';
2021-04-06 20:31:52 +02:00
include_once 'core/constants.php';
2021-04-06 16:34:12 +02:00
2021-04-07 00:03:14 +02:00
use Configuration\Configuration;
2021-04-06 20:31:52 +02:00
use Configuration\DatabaseScript;
2021-04-06 16:34:12 +02:00
use Objects\ConnectionData;
2021-04-07 00:03:14 +02:00
use Objects\User;
2021-04-06 16:34:12 +02:00
2021-04-07 00:03:14 +02:00
function printLine(string $line = "") {
echo $line . PHP_EOL;
}
function _exit(string $line = "") {
printLine($line);
2021-04-06 16:34:12 +02:00
die();
}
2021-04-07 00:03:14 +02:00
if (php_sapi_name() !== "cli") {
_exit("Can only be executed via CLI");
}
2021-04-06 16:34:12 +02:00
function getDatabaseConfig(): ConnectionData {
$configClass = "\\Configuration\\Database";
$file = getClassPath($configClass);
if (!file_exists($file) || !is_readable($file)) {
2021-04-07 00:03:14 +02:00
_exit("Database configuration does not exist or is not readable");
2021-04-06 16:34:12 +02:00
}
include_once $file;
return new $configClass();
}
2021-04-07 00:03:14 +02:00
function getUser(): User {
$config = new Configuration();
$user = new User($config);
if (!$user->getSQL() || !$user->getSQL()->isConnected()) {
_exit("Could not establish database connection");
2021-04-06 16:34:12 +02:00
}
2021-04-07 00:03:14 +02:00
return $user;
2021-04-06 16:34:12 +02:00
}
function printHelp() {
2021-04-06 23:05:02 +02:00
// TODO: help
2021-04-06 16:34:12 +02:00
}
2021-04-07 00:03:14 +02:00
function handleDatabase(array $argv) {
2021-04-06 16:34:12 +02:00
$action = $argv[2] ?? "";
2021-04-06 20:59:55 +02:00
if ($action === "migrate") {
$class = $argv[3] ?? null;
if (!$class) {
2021-04-07 00:03:14 +02:00
_exit("Usage: cli.php db migrate <class name>");
2021-04-06 20:59:55 +02:00
}
$class = str_replace('/', '\\', $class);
$className = "\\Configuration\\$class";
$classPath = getClassPath($className);
if (!file_exists($classPath) || !is_readable($classPath)) {
2021-04-07 00:03:14 +02:00
_exit("Database script file does not exist or is not readable");
2021-04-06 20:59:55 +02:00
}
include_once $classPath;
$obj = new $className();
if (!($obj instanceof DatabaseScript)) {
2021-04-07 00:03:14 +02:00
_exit("Not a database script");
2021-04-06 20:59:55 +02:00
}
2021-04-07 00:03:14 +02:00
$user = getUser();
$sql = $user->getSQL();
$queries = $obj->createQueries($sql);
2021-04-06 20:59:55 +02:00
foreach ($queries as $query) {
2021-04-07 00:03:14 +02:00
if (!$query->execute($sql)) {
_exit($sql->getLastError());
2021-04-06 20:31:52 +02:00
}
2021-04-06 20:59:55 +02:00
}
} else if ($action === "export" || $action === "import") {
// database config
$config = getDatabaseConfig();
$dbType = $config->getProperty("type") ?? null;
$user = $config->getLogin();
$password = $config->getPassword();
$database = $config->getProperty("database");
$host = $config->getHost();
$port = $config->getPort();
// subprocess config
$env = [];
$options = array_slice($argv, 3);
$dataOnly = in_array("--data-only", $options) || in_array("-d", $options);
$descriptorSpec = [STDIN, STDOUT, STDOUT];
$inputData = null;
// argument config
if ($action === "import") {
$file = $argv[3] ?? null;
if (!$file) {
2021-04-07 00:03:14 +02:00
_exit("Usage: cli.php db import <path>");
2021-04-06 20:31:52 +02:00
}
2021-04-06 20:59:55 +02:00
if (!file_exists($file) || !is_readable($file)) {
2021-04-07 00:03:14 +02:00
_exit("File not found or not readable");
2021-04-06 20:31:52 +02:00
}
2021-04-06 20:59:55 +02:00
$inputData = file_get_contents($file);
}
if ($dbType === "mysql") {
$command_args = ["-u", $user, '-h', $host, '-P', $port, "--password=$password"];
if ($action === "export") {
$command_bin = "mysqldump";
if ($dataOnly) {
$command_args[] = "--skip-triggers";
$command_args[] = "--compact";
$command_args[] = "--no-create-info";
2021-04-06 20:31:52 +02:00
}
2021-04-06 20:59:55 +02:00
} else if ($action === "import") {
$command_bin = "mysql";
$descriptorSpec[0] = ["pipe", "r"];
2021-04-06 20:31:52 +02:00
}
2021-04-06 20:59:55 +02:00
} else if ($dbType === "postgres") {
2021-04-06 20:31:52 +02:00
2021-04-06 20:59:55 +02:00
$env["PGPASSWORD"] = $password;
$command_args = ["-U", $user, '-h', $host, '-p', $port];
2021-04-06 19:01:20 +02:00
2021-04-06 20:59:55 +02:00
if ($action === "export") {
$command_bin = "/usr/bin/pg_dump";
if ($dataOnly) {
$command_args[] = "--data-only";
2021-04-06 19:01:20 +02:00
}
2021-04-06 20:59:55 +02:00
} else if ($action === "import") {
$command_bin = "/usr/bin/psql";
$descriptorSpec[0] = ["pipe", "r"];
2021-04-06 16:34:12 +02:00
}
2021-04-06 20:59:55 +02:00
} else {
2021-04-07 00:03:14 +02:00
_exit("Unsupported database type");
2021-04-06 20:59:55 +02:00
}
if ($database) {
$command_args[] = $database;
}
$command = array_merge([$command_bin], $command_args);
$process = proc_open($command, $descriptorSpec, $pipes, null, $env);
if (is_resource($process)) {
if ($action === "import" && $inputData && count($pipes) > 0) {
fwrite($pipes[0], $inputData);
fclose($pipes[0]);
2021-04-06 16:34:12 +02:00
}
proc_close($process);
2021-04-06 20:59:55 +02:00
}
2021-04-06 23:05:02 +02:00
} else {
2021-04-07 00:03:14 +02:00
_exit("Usage: cli.php db <migrate|import|export> [options...]");
2021-04-06 23:05:02 +02:00
}
}
2021-04-07 00:03:14 +02:00
function onMaintenance(array $argv) {
2021-04-06 23:05:02 +02:00
$action = $argv[2] ?? "status";
$maintenanceFile = "MAINTENANCE";
$isMaintenanceEnabled = file_exists($maintenanceFile);
if ($action === "status") {
2021-04-07 00:03:14 +02:00
_exit("Maintenance: " . ($isMaintenanceEnabled ? "on" : "off"));
2021-04-06 23:05:02 +02:00
} else if ($action === "on") {
2021-04-07 00:03:14 +02:00
$file = fopen($maintenanceFile, 'w') or _exit("Unable to create maintenance file");
2021-04-06 23:05:02 +02:00
fclose($file);
2021-04-07 00:03:14 +02:00
_exit("Maintenance enabled");
2021-04-06 23:05:02 +02:00
} else if ($action === "off") {
if (file_exists($maintenanceFile)) {
if (!unlink($maintenanceFile)) {
2021-04-07 00:03:14 +02:00
_exit("Unable to delete maintenance file");
2021-04-06 23:05:02 +02:00
}
}
2021-04-07 00:03:14 +02:00
_exit("Maintenance disabled");
} else {
_exit("Usage: cli.php maintenance <status|on|off>");
}
}
function printTable(array $head, array $body) {
$columns = [];
foreach ($head as $key) {
$columns[$key] = strlen($key);
}
foreach ($body as $row) {
foreach ($head as $key) {
$value = $row[$key] ?? "";
$length = strlen($value);
$columns[$key] = max($columns[$key], $length);
}
}
// print table
foreach ($head as $key) {
echo str_pad($key, $columns[$key]) . ' ';
}
printLine();
foreach ($body as $row) {
foreach ($head as $key) {
echo str_pad($row[$key] ?? "", $columns[$key]) . ' ';
}
printLine();
}
}
// TODO: add missing api functions (should be all internal only i guess)
function onRoutes(array $argv) {
$user = getUser();
$action = $argv[2] ?? "list";
if ($action === "list") {
$req = new Api\Routes\Fetch($user);
$success = $req->execute();
if (!$success) {
_exit("Error fetching routes: " . $req->getLastError());
} else {
$routes = $req->getResult()["routes"];
$head = ["uid", "request", "action", "target", "extra", "active"];
// strict boolean
foreach ($routes as &$route) {
$route["active"] = $route["active"] ? "true" : "false";
}
printTable($head, $routes);
}
} else if ($action === "add") {
if (count($argv) < 6) {
_exit("Usage: cli.php routes add <request> <action> <target> [extra]");
}
$params = array(
"request" => $argv[3],
"action" => $argv[4],
"target" => $argv[5],
"extra" => $argv[6] ?? ""
);
/*
$req = new Api\Routes\Add($user);
$success = $req->execute($params);
if (!$success) {
_exit($req->getLastError());
} else {
_exit("Route added successfully");
}*/
} else if (in_array($action, ["remove","modify","enable","disable"])) {
$uid = $argv[3] ?? null;
if ($uid === null || ($action === "modify" && count($argv) < 7)) {
if ($action === "modify") {
_exit("Usage: cli.php routes $action <uid> <request> <action> <target> [extra]");
} else {
_exit("Usage: cli.php routes $action <uid>");
}
}
$params = ["uid" => $uid];
if ($action === "remove") {
$input = null;
do {
if ($input === "n") {
die();
}
echo "Remove route #$uid? (y|n): ";
} while(($input = trim(fgets(STDIN))) !== "y");
// $req = new Api\Routes\Remove($user);
} else if ($action === "enable") {
// $req = new Api\Routes\Enable($user);
} else if ($action === "disable") {
// $req = new Api\Routes\Disable($user);
} else if ($action === "modify") {
// $req = new Api\Routes\Update($user);
$params["request"] = $argv[4];
$params["action"] = $argv[5];
$params["target"] = $argv[6];
$params["extra"] = $argv[7] ?? "";
} else {
_exit("Unsupported action");
}
/*
$success = $req->execute($params);
if (!$success) {
_exit($req->getLastError());
} else {
_exit("Route updated successfully");
}
*/
2021-04-06 23:05:02 +02:00
} else {
2021-04-07 00:03:14 +02:00
_exit("Usage: cli.php routes <list|enable|disable|add|remove|modify> [options...]");
2021-04-06 16:34:12 +02:00
}
}
$argv = $_SERVER['argv'];
if (count($argv) < 2) {
2021-04-07 00:03:14 +02:00
_exit("Usage: cli.php <db|routes|settings|maintenance> [options...]");
2021-04-06 16:34:12 +02:00
}
$command = $argv[1];
switch ($command) {
case 'help':
printHelp();
exit;
case 'db':
handleDatabase($argv);
break;
case 'routes':
2021-04-07 00:03:14 +02:00
onRoutes($argv);
2021-04-06 23:05:02 +02:00
break;
case 'maintenance':
onMaintenance($argv);
2021-04-06 16:34:12 +02:00
break;
default:
2021-04-07 00:03:14 +02:00
printLine("Unknown command '$command'");
printLine();
2021-04-06 16:34:12 +02:00
printHelp();
exit;
}