From 199922299d80f92e993b7feb2864e3b092a76046 Mon Sep 17 00:00:00 2001 From: Sascha Nitsch Date: Fri, 19 Jul 2024 18:28:59 +0200 Subject: [PATCH] mainenance functionality to run database updates for new releases --- .phan/config.php | 4 +- README.md | 2 + config.ini | 4 ++ maintenance.php | 95 ++++++++++++++++++++++++++++++++++++++++++++++ php/main.php | 30 +++++++++++++-- sql/2024-08-19.sql | 2 + 6 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 maintenance.php create mode 100644 sql/2024-08-19.sql diff --git a/.phan/config.php b/.phan/config.php index 8c7f84a..467e60d 100644 --- a/.phan/config.php +++ b/.phan/config.php @@ -367,5 +367,7 @@ return [ // A list of individual files to include in analysis // with a path relative to the root directory of the // project. - 'file_list' => [], + 'file_list' => [ + 'maintenance.php' + ], ]; diff --git a/README.md b/README.md index 5bf2d67..bccb773 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ Needed SQL commands: create database federator; create user if not exists 'federator'@'localhost' identified by '*change*me*'; grant select,insert,update,delete on federator.* to 'federator'@'localhost'; + create user if not exists 'federatoradmin'@'localhost' identified by '*change*me*as*well'; + grant all privileges on federator.* to 'federatoradmin'@'localhost'; This will be changed, but works for the current develop verison. diff --git a/config.ini b/config.ini index 8e0269d..a14e900 100644 --- a/config.ini +++ b/config.ini @@ -11,3 +11,7 @@ compiledir = '../cache' [plugins] rediscache = '../plugins/rediscache.php' dummy = '../plugins/dummyconnector.php' + +[maintenance] +username = 'federatoradmin' +password = '*change*me*as*well' \ No newline at end of file diff --git a/maintenance.php b/maintenance.php new file mode 100644 index 0000000..5f42688 --- /dev/null +++ b/maintenance.php @@ -0,0 +1,95 @@ +getConfig(); + $maintenance = $config['maintenance']; + $main->openDatabase($maintenance['username'], $maintenance['password']); + $dbh = $main->getDatabase(); + if ($dbh === false) { + die(); + } + $sql = 'select `value` from settings where `key`="database_version"'; + try { + $sth = $dbh->query($sql); + } catch (mysqli_sql_exception) { + $sth = false; + } + $version = '0'; + if ($sth instanceof mysqli_result) { + $row = $sth->fetch_row(); + if (is_array($row)) { + $version = $row[0]; + } + } + echo "current version: $version\n"; + $updateFolder = opendir("sql"); + if ($updateFolder === false) { + die(); + } + $updates = []; + while (($file = readdir($updateFolder)) !== false) { + $matches = []; + if (preg_match('/^(\d{4}-\d{2}-\d{2}).sql$/', $file, $matches) == 1) { + if (strcmp($matches[1], $version) > 0) { // file is newer than our version + $updates[] = $file; + } + } + } + closedir($updateFolder); + sort($updates); + foreach ($updates as $update) { + echo "applying update $update\n"; + $u = fopen('sql/' . $update, 'r'); + if ($u !== false) { + try { + $dbh->begin_transaction(); + // apply updates line by line + while (($line = fgets($u)) !== false) { + $line = trim($line); + $dbh->query($line); + } + $dbh->commit(); + } catch (mysqli_sql_exception $e) { + //print_r($e); + echo "error while applying update $update: " . $e->getMessage() . "\n"; + } + fclose($u); + } + } +} + +function printUsage() +{ + echo "usage php maintenance.php \n"; + echo "command can be one of:\n"; + echo " dbupgrade - this upgrades the db to the most recent version. Run this after you updated the program files\n"; + exit(); +} + +date_default_timezone_set("Europe/Berlin"); +spl_autoload_register(static function (string $className) { + $root = array_key_exists('DOCUMENT_ROOT', $_SERVER) ? $_SERVER['DOCUMENT_ROOT'] : ''; + // strip Federator from class path + $className = str_replace('Federator\\', '', $className); + include $root . 'php/' . str_replace("\\", "/", strtolower($className)) . '.php'; +}); + +if ($argc < 2) { + printUsage(); +} + +$main = new \Federator\Main(''); +switch ($argv[1]) { + case 'dbupgrade': + dbupgrade($main); + break; + default: + printUsage(); +} diff --git a/php/main.php b/php/main.php index e55d980..36aec45 100644 --- a/php/main.php +++ b/php/main.php @@ -3,6 +3,7 @@ /** * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop * SPDX-License-Identifier: GPL-3.0-or-later + * * @author Author: Sascha Nitsch (grumpydeveloper) **/ @@ -77,11 +78,13 @@ class Main /** * constructor + * + * @param string $rootDir root directory */ - public function __construct() + public function __construct($rootDir = '../') { $this->responseCode = 200; - $config = parse_ini_file('../config.ini', true); + $config = parse_ini_file($rootDir . 'config.ini', true); if ($config !== false) { $this->config = $config; } @@ -122,6 +125,16 @@ class Main return $this->config; } + /** + * get database handle + * + * @return \mysqli|false database handle + */ + public function getDatabase() + { + return $this->dbh; + } + /** * load plugins */ @@ -141,11 +154,20 @@ class Main /** * open database + * + * @param string|null $usernameOverride optional username override + * @param string|null $passwordOverride optional password override + * @return void */ - public function openDatabase() : void + public function openDatabase($usernameOverride = null, $passwordOverride = null) { $dbconf = $this->config["database"]; - $this->dbh = new \mysqli($dbconf['host'], $dbconf['username'], $dbconf['password'], $dbconf['database']); + $this->dbh = new \mysqli( + $dbconf['host'], + $usernameOverride ?? (string)$dbconf['username'], + $passwordOverride ?? (string)$dbconf['password'], + $dbconf['database'] + ); if ($this->dbh->connect_error !== null) { http_response_code(500); die('Database Connect Error'); diff --git a/sql/2024-08-19.sql b/sql/2024-08-19.sql new file mode 100644 index 0000000..247f588 --- /dev/null +++ b/sql/2024-08-19.sql @@ -0,0 +1,2 @@ +create table settings(`key` varchar(255) unique primary key, `value` text); +insert into settings (`key`, `value`) value ("database_version", "2024-08-19");