diff options
-rw-r--r-- | backend.php | 2 | ||||
-rw-r--r-- | classes/config.php | 11 | ||||
-rw-r--r-- | classes/db/migrations.php | 2 | ||||
-rw-r--r-- | classes/db/updater.php | 82 | ||||
-rwxr-xr-x | classes/handler/public.php | 150 | ||||
-rw-r--r-- | classes/opml.php | 6 | ||||
-rwxr-xr-x | classes/rpc.php | 2 | ||||
-rwxr-xr-x | classes/rssutils.php | 2 | ||||
-rw-r--r-- | include/functions.php | 4 | ||||
-rw-r--r-- | include/sessions.php | 24 | ||||
-rw-r--r-- | schema/ttrss_schema_mysql.sql | 0 | ||||
-rw-r--r-- | schema/ttrss_schema_pgsql.sql | 0 | ||||
-rwxr-xr-x | update.php | 48 | ||||
-rwxr-xr-x | update_daemon2.php | 2 |
14 files changed, 117 insertions, 218 deletions
diff --git a/backend.php b/backend.php index ef1184068..98c8eace6 100644 --- a/backend.php +++ b/backend.php @@ -51,7 +51,7 @@ UserHelper::load_user_plugins($_SESSION["uid"]); } - if (Db_Updater::is_update_required()) { + if (Config::is_migration_needed()) { print Errors::to_json(Errors::E_SCHEMA_MISMATCH); return; } diff --git a/classes/config.php b/classes/config.php index 30b65305a..d0c59fbbd 100644 --- a/classes/config.php +++ b/classes/config.php @@ -6,6 +6,8 @@ class Config { const T_STRING = 2; const T_INT = 3; + const SCHEMA_VERSION = 142; + // override defaults, defined below in _DEFAULTS[], via environment: DB_TYPE becomes TTRSS_DB_TYPE, etc const DB_TYPE = "DB_TYPE"; @@ -228,7 +230,7 @@ class Config { private function _get_migrations() : Db_Migrations { if (empty($this->migrations)) { $this->migrations = new Db_Migrations(); - $this->migrations->initialize(dirname(__DIR__) . "/sql", "ttrss_version", true); + $this->migrations->initialize(dirname(__DIR__) . "/sql", "ttrss_version", true, self::SCHEMA_VERSION); } return $this->migrations; @@ -336,7 +338,7 @@ class Config { $pdo = Db::pdo(); - $errors = array(); + $errors = []; if (strpos(self::get(Config::PLUGINS), "auth_") === false) { array_push($errors, "Please enable at least one authentication module via PLUGINS"); @@ -373,6 +375,11 @@ class Config { } if (php_sapi_name() != "cli") { + + if (self::get_schema_version() < 0) { + array_push($errors, "Base database schema is missing. Either load it manually or perform a migration (<code>update.php --update-schema</code>)"); + } + $ref_self_url_path = self::make_self_url(); if ($ref_self_url_path) { diff --git a/classes/db/migrations.php b/classes/db/migrations.php index e77904f60..e5133ddf6 100644 --- a/classes/db/migrations.php +++ b/classes/db/migrations.php @@ -89,7 +89,7 @@ class Db_Migrations { try { $this->pdo->query($line); } catch (PDOException $e) { - Debug::log("Failed on line: $line"); + Debug::log("Failed on line: $line", Debug::LOG_VERBOSE); throw $e; } } diff --git a/classes/db/updater.php b/classes/db/updater.php deleted file mode 100644 index 9d27c94d9..000000000 --- a/classes/db/updater.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php -class Db_Updater { - const SCHEMA_VERSION = 142; - - private $pdo; - private $db_type; - - function __construct($pdo, $db_type) { - $this->pdo = $pdo; - $this->db_type = $db_type; - } - - /** always returns actual (=uncached) value */ - private static function get_schema_version() { - return Config::get_schema_version(true); - } - - static function is_update_required() { - return self::get_schema_version() < self::SCHEMA_VERSION; - } - - function get_schema_lines($version) { - $filename = "schema/versions/".$this->db_type."/$version.sql"; - - if (file_exists($filename)) { - return explode(";", (string)preg_replace("/[\r\n]/", "", (string)file_get_contents($filename))); - } else { - user_error("DB Updater: schema file for version $version is not found."); - return false; - } - } - - function update_to($version, $html_output = true) { - if ($this->get_schema_version() == $version - 1) { - - $lines = $this->get_schema_lines($version); - - if (is_array($lines)) { - - $this->pdo->beginTransaction(); - - foreach ($lines as $line) { - if (strpos($line, "--") !== 0 && $line) { - - if ($html_output) - print "<pre>$line</pre>"; - else - Debug::log("> $line"); - - try { - $this->pdo->query($line); // PDO returns errors as exceptions now - } catch (PDOException $e) { - if ($html_output) { - print "<div class='text-error'>Error: " . $e->getMessage() . "</div>"; - } else { - Debug::log("Error: " . $e->getMessage()); - } - - $this->pdo->rollBack(); - return false; - } - } - } - - $db_version = self::get_schema_version(); - - if ($db_version == $version) { - $this->pdo->commit(); - return true; - } else { - $this->pdo->rollBack(); - return false; - } - } else { - return false; - } - } else { - return false; - } - } - -} diff --git a/classes/handler/public.php b/classes/handler/public.php index 08df7bbc1..0e82b6469 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -623,33 +623,57 @@ class Handler_Public extends Handler { <!DOCTYPE html> <html> <head> - <title>Database Updater</title> + <title>Tiny Tiny RSS: Database Updater</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> - <?= stylesheet_tag("themes/light.css") ?> - <link rel="shortcut icon" type="image/png" href="images/favicon.png"> <link rel="icon" type="image/png" sizes="72x72" href="images/favicon-72px.png"> + <link rel="shortcut icon" type="image/png" href="images/favicon.png"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <?php - echo stylesheet_tag("themes/light.css"); - echo javascript_tag("lib/dojo/dojo.js"); - echo javascript_tag("lib/dojo/tt-rss-layer.js"); - ?> + foreach (["lib/dojo/dojo.js", + "lib/dojo/tt-rss-layer.js", + "js/common.js", + "js/utility.js"] as $jsfile) { + + echo javascript_tag($jsfile); + + } ?> + + <?php if (theme_exists(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET))) { + echo stylesheet_tag(get_theme_path(Config::get(Config::LOCAL_OVERRIDE_STYLESHEET))); + } ?> + <style type="text/css"> - span.ok { color : #009000; font-weight : bold; } - span.err { color : #ff0000; font-weight : bold; } + @media (prefers-color-scheme: dark) { + body { + background : #303030; + } + } + + body.css_loading * { + display : none; + } </style> + + <script type="text/javascript"> + require({cache:{}}); + </script> </head> - <body class="flat ttrss_utility"> + <body class="flat ttrss_utility css_loading"> <script type="text/javascript"> - require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', - 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser, ready){ - ready(function() { - parser.parse(); - }); - }); - - function confirmOP() { - return confirm("Update the database?"); + const UtilityApp = { + init: function() { + require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', + 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser, ready){ + ready(function() { + parser.parse(); + }); + }); + } + } + + function confirmDbUpdate() { + return confirm(__("Proceed with update?")); } </script> @@ -660,72 +684,66 @@ class Handler_Public extends Handler { <?php @$op = clean($_REQUEST["subop"] ?? ""); - $updater = new Db_Updater(Db::pdo(), Config::get(Config::DB_TYPE)); - - if ($op == "performupdate") { - if (Db_Updater::is_update_required()) { - - print "<h2>" . T_sprintf("Performing updates to version %d", Db_Updater::SCHEMA_VERSION) . "</h2>"; - for ($i = Config::get_schema_version(true) + 1; $i <= Db_Updater::SCHEMA_VERSION; $i++) { - print "<ul>"; + $migrations = Config::get_migrations(); - print "<li class='text-info'>" . T_sprintf("Updating to version %d", $i) . "</li>"; + if ($op == "performupdate") { + if ($migrations->is_migration_needed()) { + ?> - print "<li>"; - $result = $updater->update_to($i, true); - print "</li>"; + <h2><?= T_sprintf("Performing updates to version %d", Config::SCHEMA_VERSION) ?></h2> - if (!$result) { - print "</ul>"; + <code><pre class="small pre-wrap"><?php + Debug::set_enabled(true); + Debug::set_loglevel(Debug::LOG_VERBOSE); + $result = $migrations->migrate(); + Debug::set_loglevel(Debug::LOG_NORMAL); + Debug::set_enabled(false); + ?></pre></code> - print_error("One of the updates failed. Either retry the process or perform updates manually."); + <?php if (!$result) { ?> + <?= format_error("One of migrations failed. Either retry the process or perform updates manually.") ?> - print "<form method='POST'> - <input type='hidden' name='subop' value='performupdate'> - <button type='submit' dojoType='dijit.form.Button' class='alt-danger' onclick='return confirmOP()'>".__("Try again")."</button> - <a href='index.php'>".__("Return to Tiny Tiny RSS")."</a> - </form>"; + <form method="post"> + <?= \Controls\hidden_tag('subop', 'performupdate') ?> + <?= \Controls\submit_tag(__("Update"), ["onclick" => "return confirmDbUpdate()"]) ?> + </form> + <?php } else { ?> + <?= format_notice("Update successful.") ?> - return; - } else { - print "<li class='text-success'>" . __("Completed.") . "</li>"; - print "</ul>"; - } - } + <a href="index.php"><?= __("Return to Tiny Tiny RSS") ?></a> + <?php } - print_notice("Your Tiny Tiny RSS database is now updated to the latest version."); + } else { ?> - print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>"; + <?= format_notice("Database is already up to date.") ?> - } else { - print_notice("Tiny Tiny RSS database is up to date."); + <a href="index.php"><?= __("Return to Tiny Tiny RSS") ?></a> - print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>"; + <?php } } else { - if (Db_Updater::is_update_required()) { + if ($migrations->is_migration_needed()) { - print "<h2>".T_sprintf("Tiny Tiny RSS database needs update to the latest version (%d to %d).", - Config::get_schema_version(true), Db_Updater::SCHEMA_VERSION)."</h2>"; + ?> + <h2><?= T_sprintf("Database schema needs update to the latest version (%d to %d).", + Config::get_schema_version(), Config::SCHEMA_VERSION) ?></h2> - if (Config::get(Config::DB_TYPE) == "mysql") { - print_error("<strong>READ THIS:</strong> Due to MySQL limitations, your database is not completely protected while updating. ". - "Errors may put it in an inconsistent state requiring manual rollback. <strong>BACKUP YOUR DATABASE BEFORE CONTINUING.</strong>"); - } else { - print_warning("Please backup your database before proceeding."); - } + <?= format_warning("Please backup your database before proceeding.") ?> - print "<form method='POST'> - <input type='hidden' name='subop' value='performupdate'> - <button type='submit' dojoType='dijit.form.Button' class='alt-danger' onclick='return confirmOP()'>".__("Perform updates")."</button> - </form>"; + <form method="post"> + <?= \Controls\hidden_tag('subop', 'performupdate') ?> + <?= \Controls\submit_tag(__("Update"), ["onclick" => "return confirmDbUpdate()"]) ?> + </form> - } else { + <?php + } else { ?> + + <?= format_notice("Database is already up to date.") ?> - print_notice("Tiny Tiny RSS database is up to date."); + <a href="index.php"><?= __("Return to Tiny Tiny RSS") ?></a> - print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>"; + <?php } } ?> diff --git a/classes/opml.php b/classes/opml.php index 1a223788f..f8e9f6728 100644 --- a/classes/opml.php +++ b/classes/opml.php @@ -151,7 +151,7 @@ class OPML extends Handler_Protected { # export tt-rss settings if ($include_settings) { - $out .= "<outline text=\"tt-rss-prefs\" schema-version=\"".Db_Updater::SCHEMA_VERSION."\">"; + $out .= "<outline text=\"tt-rss-prefs\" schema-version=\"".Config::SCHEMA_VERSION."\">"; $sth = $this->pdo->prepare("SELECT pref_name, value FROM ttrss_user_prefs2 WHERE profile IS NULL AND owner_uid = ? ORDER BY pref_name"); @@ -166,7 +166,7 @@ class OPML extends Handler_Protected { $out .= "</outline>"; - $out .= "<outline text=\"tt-rss-labels\" schema-version=\"".Db_Updater::SCHEMA_VERSION."\">"; + $out .= "<outline text=\"tt-rss-labels\" schema-version=\"".Config::SCHEMA_VERSION."\">"; $sth = $this->pdo->prepare("SELECT * FROM ttrss_labels2 WHERE owner_uid = ?"); @@ -183,7 +183,7 @@ class OPML extends Handler_Protected { $out .= "</outline>"; - $out .= "<outline text=\"tt-rss-filters\" schema-version=\"".Db_Updater::SCHEMA_VERSION."\">"; + $out .= "<outline text=\"tt-rss-filters\" schema-version=\"".Config::SCHEMA_VERSION."\">"; $sth = $this->pdo->prepare("SELECT * FROM ttrss_filters2 WHERE owner_uid = ? ORDER BY id"); diff --git a/classes/rpc.php b/classes/rpc.php index 90c2c762a..054b711bc 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -181,7 +181,7 @@ class RPC extends Handler_Protected { $client_scheme = parse_url($client_location, PHP_URL_SCHEME); $server_scheme = parse_url(Config::get_self_url(), PHP_URL_SCHEME); - if (Db_Updater::is_update_required()) { + if (Config::is_migration_needed()) { $error = Errors::E_SCHEMA_MISMATCH; } else if ($client_scheme != $server_scheme) { $error = Errors::E_URL_SCHEME_MISMATCH; diff --git a/classes/rssutils.php b/classes/rssutils.php index 0d78e0ec7..9480c0b0b 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -55,7 +55,7 @@ class RSSUtils { static function update_daemon_common($limit = null, $options = []) { if (!$limit) $limit = Config::get(Config::DAEMON_FEED_LIMIT); - if (Config::get_schema_version() != Db_Updater::SCHEMA_VERSION) { + if (Config::get_schema_version() != Config::SCHEMA_VERSION) { die("Schema version is wrong, please upgrade the database.\n"); } diff --git a/include/functions.php b/include/functions.php index 4d11ea31f..5e75439cf 100644 --- a/include/functions.php +++ b/include/functions.php @@ -2,8 +2,8 @@ define('LABEL_BASE_INDEX', -1024); define('PLUGIN_FEED_BASE_INDEX', -128); - /** constant is @deprecated, use Db_Updater::SCHEMA_VERSION instead */ - define('SCHEMA_VERSION', Db_Updater::SCHEMA_VERSION); + /** constant is @deprecated, use Config::SCHEMA_VERSION instead */ + define('SCHEMA_VERSION', Config::SCHEMA_VERSION); if (version_compare(PHP_VERSION, '8.0.0', '<')) { libxml_disable_entity_loader(true); diff --git a/include/sessions.php b/include/sessions.php index 3a1a3b8cd..cda42f52b 100644 --- a/include/sessions.php +++ b/include/sessions.php @@ -122,17 +122,19 @@ return true; } - if (!\Config::get(\Config::SINGLE_USER_MODE)) { - session_set_save_handler('\Sessions\ttrss_open', - '\Sessions\ttrss_close', '\Sessions\ttrss_read', - '\Sessions\ttrss_write', '\Sessions\ttrss_destroy', - '\Sessions\ttrss_gc'); - register_shutdown_function('session_write_close'); - } + if (\Config::get_schema_version() >= 0) { + if (!\Config::get(\Config::SINGLE_USER_MODE)) { + session_set_save_handler('\Sessions\ttrss_open', + '\Sessions\ttrss_close', '\Sessions\ttrss_read', + '\Sessions\ttrss_write', '\Sessions\ttrss_destroy', + '\Sessions\ttrss_gc'); + register_shutdown_function('session_write_close'); + } - if (!defined('NO_SESSION_AUTOSTART')) { - if (isset($_COOKIE[session_name()])) { - if (session_status() != PHP_SESSION_ACTIVE) - session_start(); + if (!defined('NO_SESSION_AUTOSTART')) { + if (isset($_COOKIE[session_name()])) { + if (session_status() != PHP_SESSION_ACTIVE) + session_start(); + } } } diff --git a/schema/ttrss_schema_mysql.sql b/schema/ttrss_schema_mysql.sql new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/schema/ttrss_schema_mysql.sql diff --git a/schema/ttrss_schema_pgsql.sql b/schema/ttrss_schema_pgsql.sql new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/schema/ttrss_schema_pgsql.sql diff --git a/update.php b/update.php index d19c5f823..ad5704a7d 100755 --- a/update.php +++ b/update.php @@ -378,7 +378,7 @@ if (read_stdin() != 'yes') exit; } else { - Debug::log("Proceeding to update without confirmation..."); + Debug::log("Proceeding to update without confirmation."); } if (!isset($options["log-level"])) { @@ -386,57 +386,11 @@ } $migrations = Config::get_migrations(); - - Debug::log("Migrating schema to version " . $migrations->get_max_version()); - $migrations->migrate(); } else { Debug::log("Database schema is already at latest version."); } - - /*Debug::log("Checking for updates (" . Config::get(Config::DB_TYPE) . ")..."); - - $updater = new Db_Updater(Db::pdo(), Config::get(Config::DB_TYPE)); - - if (Db_Updater::is_update_required()) { - Debug::log("Schema update required, version " . Config::get_schema_version(true) . " to " . Db_Updater::SCHEMA_VERSION); - - if (Config::get(Config::DB_TYPE) == "mysql") - Debug::Log("READ THIS: Due to MySQL limitations, your database is not completely protected while updating.\n". - "Errors may put it in an inconsistent state requiring manual rollback.\nBACKUP YOUR DATABASE BEFORE CONTINUING."); - else - Debug::log("WARNING: please backup your database before continuing."); - - if ($options["update-schema"] != "force-yes") { - Debug::log("Type 'yes' to continue."); - - if (read_stdin() != 'yes') - exit; - } else { - Debug::log("Proceeding to update without confirmation..."); - } - - Debug::log("Performing updates to version " . Db_Updater::SCHEMA_VERSION . "..."); - - for ($i = Config::get_schema_version(true) + 1; $i <= Db_Updater::SCHEMA_VERSION; $i++) { - Debug::log("* Updating to version $i..."); - - $result = $updater->update_to($i, false); - - if ($result) { - Debug::log("* Completed."); - } else { - Debug::log("One of the updates failed. Either retry the process or perform updates manually."); - return; - } - } - - Debug::log("All done."); - } else { - Debug::log("Database schema is already at latest version."); - } */ - } if (isset($options["gen-search-idx"])) { diff --git a/update_daemon2.php b/update_daemon2.php index 17bca48ee..8931813ff 100755 --- a/update_daemon2.php +++ b/update_daemon2.php @@ -189,7 +189,7 @@ "Maybe another daemon is already running.\n"); } - if (Db_Updater::is_update_required()) { + if (Config::is_migration_needed()) { die("Schema version is wrong, please upgrade the database.\n"); } |